001/*
002 * Copyright (c) 2010 The Regents of the University of California.
003 * All rights reserved.
004 *
005 * '$Author: welker $'
006 * '$Date: 2010-05-06 05:21:26 +0000 (Thu, 06 May 2010) $' 
007 * '$Revision: 24234 $'
008 * 
009 * Permission is hereby granted, without written agreement and without
010 * license or royalty fees, to use, copy, modify, and distribute this
011 * software and its documentation for any purpose, provided that the above
012 * copyright notice and the following two paragraphs appear in all copies
013 * of this software.
014 *
015 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
016 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
017 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
018 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
019 * SUCH DAMAGE.
020 *
021 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
022 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
023 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
024 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
025 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
026 * ENHANCEMENTS, OR MODIFICATIONS.
027 *
028 */
029
030/*
031 * Created on Jul 12, 2004
032 *
033 * TODO To change the template for this generated file go to
034 * Window - Preferences - Java - Code Generation - Code and Comments
035 */
036package org.ecoinformatics.seek.querybuilder;
037
038import java.io.BufferedReader;
039import java.io.File;
040import java.io.FileReader;
041import java.io.StringReader;
042import java.util.Enumeration;
043import java.util.Vector;
044
045import javax.swing.JComboBox;
046import javax.xml.parsers.DocumentBuilder;
047import javax.xml.parsers.DocumentBuilderFactory;
048import javax.xml.transform.TransformerFactory;
049import javax.xml.transform.dom.DOMResult;
050import javax.xml.transform.dom.DOMSource;
051
052import org.kepler.objectmanager.data.db.DSSchemaIFace;
053import org.kepler.objectmanager.data.db.DSTableFieldIFace;
054import org.kepler.objectmanager.data.db.DSTableIFace;
055import org.w3c.dom.Document;
056import org.w3c.dom.NamedNodeMap;
057import org.w3c.dom.Node;
058import org.w3c.dom.NodeList;
059import org.xml.sax.InputSource;
060
061/**
062 * A set of uttiliy methods (all static)
063 */
064public class DBUIUtils {
065        public static final String ALL_FIELDS = "*";
066        public static final String NO_NAME = "  ";
067
068        /**
069         * Helper method to fill combobox with the list of field names from a
070         * "named" table schema
071         * 
072         * @param aSchema
073         *            the schema
074         * @param aTableName
075         *            the table name in the schema
076         * @param aCBX
077         *            the comboxbox
078         * @param aInclAstrick
079         *            if the table schema includes a field with an astrick "*" then
080         *            include it also
081         */
082        public static void fillFieldCombobox(DSSchemaIFace aSchema,
083                        String aTableName, JComboBox aCBX, boolean aInclAstrick) {
084                if (!aTableName.equals("  ")) {
085                        aCBX.removeAllItems();
086                        if (aInclAstrick) {
087                                aCBX.addItem("*");
088                        }
089
090                        Vector tables = aSchema.getTables();
091                        if (tables != null && tables.size() > 0) {
092                                for (Enumeration et = tables.elements(); et.hasMoreElements();) {
093                                        DSTableIFace table = (DSTableIFace) et.nextElement();
094                                        if (table.getName().equals(aTableName)) {
095                                                Vector fields = table.getFields();
096                                                for (Enumeration ef = fields.elements(); ef
097                                                                .hasMoreElements();) {
098                                                        DSTableFieldIFace field = (DSTableFieldIFace) ef
099                                                                        .nextElement();
100                                                        if (aInclAstrick || !field.getName().equals("*")) {
101                                                                aCBX.addItem(field.getName());
102                                                        }
103                                                }
104                                        }
105                                }
106                        }
107                }
108        }
109
110        /**
111         * Helper method to fill combobox with the list of table names from the
112         * schema
113         * 
114         * @param aSchema
115         *            the schema
116         * @param aCBX
117         *            the comboxbox
118         */
119        public static void fillTableCombobox(DSSchemaIFace aSchema, JComboBox aCBX) {
120                Vector tables = aSchema.getTables();
121                if (tables != null && tables.size() > 0) {
122                        for (Enumeration et = tables.elements(); et.hasMoreElements();) {
123                                DSTableIFace table = (DSTableIFace) et.nextElement();
124                                aCBX.addItem(table.getName());
125                        }
126                }
127        }
128
129        /**
130         * Add brackets around names with spaces
131         * 
132         * @param aName
133         *            the name to be changed
134         * @return a name with brackets, but only if necessary
135         */
136        public static String fixNameWithSpaces(String aName) {
137                if (aName.indexOf(' ') != -1)
138                        return "[" + aName + "]";
139                else
140                        return aName;
141        }
142
143        /**
144         * Returns the full table name/field name concatenated
145         * 
146         * @param aField
147         *            object for which to get the names
148         * @return the full name
149         */
150        public static String getFullFieldName(DBTableField aField) {
151                StringBuffer strBuf = new StringBuffer();
152                strBuf.append(fixNameWithSpaces(aField.getTable().getName()));
153                strBuf.append(".");
154                strBuf.append(fixNameWithSpaces(aField.getName()));
155                return strBuf.toString();
156        }
157
158        /**
159         * Returns the full table name/field name concatenated
160         * 
161         * @param aTblName
162         *            the table name
163         * @param aFieldName
164         *            the field name
165         * @return the concatenated name
166         */
167        public static String getFullFieldName(String aTblName, String aFieldName) {
168                StringBuffer strBuf = new StringBuffer();
169                strBuf.append(fixNameWithSpaces(aTblName));
170                strBuf.append(".");
171                strBuf.append(fixNameWithSpaces(aFieldName));
172                return strBuf.toString();
173        }
174
175        /**
176         * Returns a table by name
177         * 
178         * @param aName
179         *            name of table to be found
180         *       */
181        protected static DSTableIFace getTableByName(DSSchemaIFace aSchema,
182                        String aName) {
183                if (aSchema != null) {
184                        Vector tables = aSchema.getTables();
185                        for (int i = 0; i < tables.size(); i++) {
186                                DSTableIFace table = (DSTableIFace) tables.elementAt(i);
187                                if (table.getName().equals(aName))
188                                        return table;
189                        }
190                }
191                return null;
192        }
193
194        /**
195         * Returns a DBTableField object by name
196         * 
197         * @param aTable
198         *            table to look into
199         * @param aName
200         *            name of field to be found
201         * @return field object
202         */
203        public static DSTableFieldIFace getFieldByName(DSTableIFace aTable,
204                        String aName) {
205                if (aTable != null) {
206                        Vector fields = aTable.getFields();
207                        for (int i = 0; i < fields.size(); i++) {
208                                DSTableFieldIFace field = (DSTableFieldIFace) fields
209                                                .elementAt(i);
210                                // System.out.println("["+field.getName()+"]["+aName+"]");
211                                if (field.getName().equals(aName))
212                                        return field;
213                        }
214                }
215                return null;
216        }
217
218        /**
219         * Returns a DBTableField object by name
220         * 
221         * @param aSchema
222         *            schema
223         * @param aTableName
224         *            table name to look into
225         * @param aFieldName
226         *            name of field to be found
227         * @return field object
228         */
229        public static DSTableFieldIFace getFieldByName(DSSchemaIFace aSchema,
230                        String aTableName, String aFieldName) {
231                Vector tables = aSchema.getTables();
232                if (tables != null && tables.size() > 0) {
233                        for (Enumeration et = tables.elements(); et.hasMoreElements();) {
234                                DSTableIFace table = (DSTableIFace) et.nextElement();
235                                if (table.getName().equals(aTableName)) {
236                                        Vector fields = table.getFields();
237                                        for (Enumeration ef = fields.elements(); ef
238                                                        .hasMoreElements();) {
239                                                DSTableFieldIFace field = (DSTableFieldIFace) ef
240                                                                .nextElement();
241                                                if (field.getName().equals(aFieldName)) {
242                                                        return field;
243                                                }
244                                        }
245                                }
246                        }
247                }
248                return null;
249        }
250
251        /**
252         * Removes the brackets from a name that has one of spaces in it
253         * 
254         * @param aName
255         *            the name
256         * @return the new name w/o the brackts
257         */
258        private static String removeBrackets(String aName) {
259                if (aName == null || aName.length() == 0)
260                        return "";
261
262                int startInx = aName.indexOf("[");
263                int endInx = aName.length();
264                if (startInx != -1) {
265                        endInx = aName.indexOf("]");
266                        if (endInx == -1) {
267                                return "";
268                        }
269                        endInx--;
270                } else {
271                        startInx = 0;
272                }
273                return aName.substring(startInx, endInx);
274        }
275
276        /**
277         * Returns true if the name is of format "table name"."field name" and the
278         * table name and field name are in the schema
279         * 
280         * @param aSchema
281         *            schema
282         * @param aName
283         *            the full name
284         * @param aTableName
285         *            can be null, or a stringbuffer that will return the name of
286         *            the table
287         * @return Returns true if the name is of format "table name"."field name"
288         *         and the table name and field name are in the schema
289         */
290        public static DSTableFieldIFace isTableFieldName(DSSchemaIFace aSchema,
291                        String aName, StringBuffer aTableName) {
292                int sepInx = aName.indexOf(".");
293                if (sepInx == -1)
294                        return null;
295
296                String tableName = removeBrackets(aName.substring(0, sepInx));
297                String fieldName = removeBrackets(aName.substring(sepInx + 1, aName
298                                .length()));
299                if (aTableName != null) {
300                        aTableName.setLength(0);
301                        aTableName.append(tableName);
302                }
303                return getFieldByName(aSchema, tableName, fieldName);
304        }
305
306        /**
307         * Returns the desired number of spaces for the depth (usually *2)
308         * 
309         * @param aDepth
310         *            the depth
311         * @return spaces
312         */
313        public static String getSpaces(int aDepth) {
314                StringBuffer strBuf = new StringBuffer();
315                for (int i = 0; i < aDepth; i++) {
316                        strBuf.append("  ");
317                }
318                return strBuf.toString();
319        }
320
321        // ------------------------------------------------------------
322        // ------------------------------------------------------------
323        // -- Common DOM and XML Utilities
324        // ------------------------------------------------------------
325        // ------------------------------------------------------------
326
327        /**
328         * ------------------------------------------------------------ Gets the
329         * String value of a node. First checks it's value and if that is null then
330         * it checks to see if it has a child node and gets the value of the first
331         * child. Assumption: That the first child is a #text node, delibertly NOT
332         * checking the first node's type
333         * 
334         * @param aNode
335         *            Parent to search (should be the document root)
336         * @return Returns the value of the node
337         *         --------------------------------------------------------------
338         */
339        public static String getNodeValue(Node aNode) {
340                String value = null;
341                if (aNode.getNodeValue() != null) {
342                        value = aNode.getNodeValue() != null ? aNode.getNodeValue().trim()
343                                        : null;
344                } else {
345                        NodeList list = aNode.getChildNodes();
346                        if (list.getLength() == 1) {
347                                Node child = list.item(0);
348                                if (child != null) {
349                                        value = child.getNodeValue() != null ? child.getNodeValue()
350                                                        .trim() : null;
351                                }
352                        }
353                }
354                return value;
355        }
356
357        /**
358         * ------------------------------------------------------------ Finds the
359         * first node of a given type
360         * 
361         * @param aNode
362         *            Parent to search (should be the document root)
363         * @param aName
364         *            Name of node to find
365         * @return Returns the node of that name or null
366         *         --------------------------------------------------------------
367         */
368        public static Node findNode(Node aNode, String aName) {
369                String name = aNode.getNodeName() != null ? aNode.getNodeName().trim()
370                                : "";
371                if (aName.equalsIgnoreCase(name)) {
372                        return aNode;
373                }
374
375                NodeList list = aNode.getChildNodes();
376                for (int i = 0; i < list.getLength(); i++) {
377                        Node child = list.item(i);
378                        if (child != null) {
379                                Node node = findNode(child, aName);
380                                if (node != null) {
381                                        return node;
382                                }
383                        }
384                }
385                return null;
386        }
387
388        /**
389         * ------------------------------------------------------------ Gets the
390         * value of the named node
391         * 
392         * @param aNode
393         *            Parent to search (should be the document root)
394         * @param aName
395         *            Name of node to find
396         * @return Returns the node's value as a string
397         *         --------------------------------------------------------------
398         */
399        public static String findNodeValue(Node aNode, String aName) {
400                String value = null;
401                Node node = findNode(aNode, aName);
402                if (node != null) {
403                        value = getNodeValue(node);
404                }
405                return value;
406        }
407
408        /**
409         * ------------------------------------------------------------ Gets an
410         * attribute value for the named node.
411         * 
412         * @param aNode
413         *            Parent to search (should be the document root)
414         * @param aName
415         *            Name of node to find
416         * @param aAttr
417         *            Name of attribute to return
418         * @return Returns the attribute's value as a string
419         *         --------------------------------------------------------------
420         */
421        public static String findAttrValueForNode(Node aNode, String aName,
422                        String aAttr) {
423                String value = null;
424                Node node = findNode(aNode, aName);
425                if (node != null) {
426                        NamedNodeMap map = node.getAttributes();
427                        if (map != null) {
428                                Node attrNode = map.getNamedItem(aAttr);
429                                if (attrNode != null) {
430                                        value = getNodeValue(attrNode);
431                                }
432                        }
433                }
434                return value;
435        }
436
437        /**
438         * ------------------------------------------------------------ Gets an
439         * attribute value for the node.
440         * 
441         * @param aNode
442         *            Parent to search (should be the document root)
443         * @param aAttr
444         *            Name of attribute to return
445         * @return Returns the attribute's value as a string
446         *         --------------------------------------------------------------
447         */
448        public static String findAttrValue(Node aNode, String aAttr) {
449                String value = null;
450                if (aNode != null) {
451                        NamedNodeMap map = aNode.getAttributes();
452                        if (map != null) {
453                                Node attrNode = map.getNamedItem(aAttr);
454                                if (attrNode != null) {
455                                        value = getNodeValue(attrNode);
456                                }
457                        }
458                }
459                return value;
460        }
461
462        /**
463         * Looks up the attr and returns the int of it or returns -1
464         * 
465         * @param aNode
466         *            the node with the attr
467         * @return the int or returns -1
468         */
469        public static int getIntAttrId(Node aNode, String aAttrName) {
470                String idStr = findAttrValue(aNode, aAttrName);
471                if (idStr != null && idStr.length() > 0) {
472                        try {
473                                int id = Integer.parseInt(idStr);
474                                if (id > -1 && id < Integer.MAX_VALUE) {
475                                        return id;
476                                }
477                        } catch (NumberFormatException e) {
478                        }
479                }
480                return -1;
481        }
482
483        /**
484         * Prints a DOM Tree (recursive)
485         * 
486         * @param aNode
487         *            parent node of tree to be printed
488         * @param aLevel
489         *            indicates the current indentation level
490         */
491        public static void printNode(Node aNode, int aLevel) {
492                if (aNode == null) {
493                        return;
494                }
495
496                String spaces = "";
497                for (int i = 0; i < aLevel; i++) {
498                        spaces += "..";
499                }
500
501                System.out.println(spaces + "Name:  " + aNode.getNodeName());
502                System.out.println(spaces + "Type:  " + aNode.getNodeType());
503                System.out.println(spaces + "Value: " + aNode.getNodeValue());
504                NodeList list = aNode.getChildNodes();
505                if (list != null) {
506                        for (int i = 0; i < list.getLength(); i++) {
507                                Node child = list.item(i);
508                                printNode(child, aLevel + 1);
509                        }
510                }
511        }
512
513        /**
514         * Reads in an XML document and returns a String of the file's contents
515         * 
516         * @param aFileName
517         *            file name of XML file to be read
518         */
519        public static String readXMLFile2Str(String aFileName) {
520                try {
521                        FileReader fileReader = new FileReader(aFileName);
522                        BufferedReader bufReader = new BufferedReader(fileReader);
523                        StringBuffer strBuf = new StringBuffer();
524
525                        String line = bufReader.readLine();
526                        while (line != null) {
527                                strBuf.append(line);
528                                strBuf.append("\n");
529                                line = bufReader.readLine();
530                        }
531                        return strBuf.toString();
532
533                } // try
534                catch (Exception e) {
535                        System.err.println("readXMLFile2Str - Exception: " + e);
536                }
537                return null;
538        }
539
540        /**
541         * Reads in an XML document and returns the Document node of the DOM tree
542         * 
543         * @param aFileName
544         *            file name of XML file to be read
545         */
546        public static Document readXMLFile2DOM(String aFileName) {
547                File file = new File(aFileName);
548                if (!file.exists())
549                        return null;
550                try {
551                        TransformerFactory tFactory = TransformerFactory.newInstance();
552
553                        if (tFactory.getFeature(DOMSource.FEATURE)
554                                        && tFactory.getFeature(DOMResult.FEATURE)) {
555                                // Instantiate a DocumentBuilderFactory.
556                                DocumentBuilderFactory dFactory = DocumentBuilderFactory
557                                                .newInstance();
558
559                                // And setNamespaceAware, which is required when parsing xsl
560                                // files
561                                dFactory.setNamespaceAware(true);
562
563                                // Use the DocumentBuilderFactory to create a DocumentBuilder.
564                                DocumentBuilder dBuilder = dFactory.newDocumentBuilder();
565
566                                // Use the DocumentBuilder to parse the XML input.
567                                Document xmlDoc = dBuilder.parse(aFileName);
568
569                                // printNode(xmlDoc, 0);
570
571                                return xmlDoc;
572
573                        }
574                } // try
575                catch (org.xml.sax.SAXParseException e) {
576                        System.err.println("Tried Reading[" + aFileName + "]");
577                        System.err.println("readXMLFile2DOM - Exception: " + e);
578                        // String xmlString = readXMLFile2Str(aFileName);
579                        // System.out.println("XML Dump " + aFileName);
580                        // System.out.println("------------------------------------------");
581                        // System.out.println(xmlString);
582                        // System.out.println("------------------------------------------");
583                } catch (Exception e) {
584                        System.err.println("Tried Reading[" + aFileName + "]");
585                        System.err.println("readXMLFile2DOM - Exception: " + e);
586                }
587                return null;
588        }
589
590        /**
591         * Convert/Parses an XML string into a DOM tree
592         * 
593         * @param aXMLStr
594         *            XML string (document)
595         */
596        public static Document convertXMLStr2DOM(String aXMLStr) {
597                try {
598                        TransformerFactory tFactory = TransformerFactory.newInstance();
599
600                        if (tFactory.getFeature(DOMSource.FEATURE)
601                                        && tFactory.getFeature(DOMResult.FEATURE)) {
602                                // Instantiate a DocumentBuilderFactory.
603                                DocumentBuilderFactory dFactory = DocumentBuilderFactory
604                                                .newInstance();
605
606                                // And setNamespaceAware, which is required when parsing xsl
607                                // files
608                                dFactory.setNamespaceAware(true);
609
610                                // Use the DocumentBuilderFactory to create a DocumentBuilder.
611                                DocumentBuilder dBuilder = dFactory.newDocumentBuilder();
612
613                                StringReader strReader = new StringReader(aXMLStr);
614                                InputSource inpSrc = new InputSource(strReader);
615
616                                // Use the DocumentBuilder to parse the XML input.
617                                Document xmlDoc = dBuilder.parse(inpSrc);
618
619                                return xmlDoc;
620
621                        }
622                } // try
623                catch (Exception e) {
624                        System.err.println("convertXMLStr2DOM - Exception: " + e);
625                        System.err.println("XML Dump");
626                        System.err.println("------------------------------------------");
627                        System.err.println(aXMLStr);
628                        System.err.println("------------------------------------------");
629                        e.printStackTrace();
630                }
631                return null;
632        }
633
634}