001/*
002 * Copyright (c) 2003-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
030package org.ecoinformatics.seek.querybuilder;
031
032import java.util.Enumeration;
033import java.util.Vector;
034
035import org.kepler.objectmanager.data.db.DSSchemaDef;
036import org.kepler.objectmanager.data.db.DSSchemaIFace;
037import org.kepler.objectmanager.data.db.DSTableDef;
038import org.kepler.objectmanager.data.db.DSTableFieldIFace;
039import org.kepler.objectmanager.data.db.DSTableIFace;
040import org.kepler.objectmanager.data.db.DSTableKeyIFace;
041import org.w3c.dom.Document;
042import org.w3c.dom.Node;
043import org.w3c.dom.NodeList;
044
045/**
046 * This class can generate XML from a DSSchemaIFace object or create a schema
047 * from and XML dcoument
048 */
049public class DBSchemaParserEmitter {
050        private static final String[] KEY_DESC = { "", "PRIMARYKEY", "SECONDARYKEY" };
051        private static String MISSINGVALUELIST = "missingValueCodeList";
052        private static String MISSINGVALUECODE = "missingValueCode";
053
054        /**
055         * Create a DSSchemaIFace object from an XML DOM
056         * 
057         * @param aDoc
058         *            the DOM
059         * @return the schema object
060         */
061        public static DSSchemaIFace processDOM(Document aDoc) {
062                DSSchemaDef schemaDef = new DSSchemaDef();
063                Node schemaNode = DBUIUtils.findNode(aDoc, "schema");
064                if (schemaNode == null) {
065                        System.out.println("*** Error DOM is missing its schema node!");
066                        schemaDef = null;
067                        return null;
068                }
069
070                NodeList tableList = schemaNode.getChildNodes();
071                if (tableList != null) {
072                        for (int i = 0; i < tableList.getLength(); i++) {
073                                Node tableNode = tableList.item(i);
074                                if (tableNode.getNodeType() != Node.TEXT_NODE) {
075                                        String nodeName = tableNode.getNodeName();
076                                        if (nodeName != null && nodeName.equals("table")) {
077                                                String name = DBUIUtils
078                                                                .findAttrValue(tableNode, "name");
079                                                if (name != null && name.length() > 0) {
080                                                        DSTableDef tableDef = new DSTableDef(name);
081                                                        schemaDef.addTable(tableDef);
082                                                        NodeList fieldList = tableNode.getChildNodes();
083                                                        if (fieldList != null) {
084                                                                for (int j = 0; j < fieldList.getLength(); j++) {
085                                                                        Node field = fieldList.item(j);
086                                                                        if (field != null
087                                                                                        && field.getNodeType() != Node.TEXT_NODE) {
088                                                                                String fldName = DBUIUtils
089                                                                                                .findAttrValue(field, "name");
090                                                                                if (fldName == null
091                                                                                                || fldName.length() == 0) {
092                                                                                        System.out
093                                                                                                        .println("*** Error field DOM node is missing its name!");
094                                                                                        return null;
095                                                                                }
096                                                                                String dataType = DBUIUtils
097                                                                                                .findAttrValue(field,
098                                                                                                                "dataType");
099                                                                                if (dataType == null
100                                                                                                || dataType.length() == 0) {
101                                                                                        System.out
102                                                                                                        .println("*** Error field DOM node is missing its data type!");
103                                                                                        return null;
104                                                                                }
105
106                                                                                // handle missing value
107                                                                                Node missingValueList = DBUIUtils
108                                                                                                .findNode(field,
109                                                                                                                MISSINGVALUELIST);
110                                                                                Vector missingValueCodeVector = new Vector();
111                                                                                // System.out.println("before parsing missing value in schema parser");
112                                                                                if (missingValueList != null) {
113                                                                                        // System.out.println("after missingValue list is not null1");
114                                                                                        NodeList missingValue = missingValueList
115                                                                                                        .getChildNodes();
116                                                                                        // System.out.println("after get missing value list kids2");
117                                                                                        if (missingValue != null) {
118                                                                                                // System.out.println("after missingvalue list is not null3");
119                                                                                                for (int k = 0; k < missingValue
120                                                                                                                .getLength(); k++) {
121                                                                                                        // System.out.println("in missing value element4");
122                                                                                                        Node missingcodeNode = missingValue
123                                                                                                                        .item(k);
124                                                                                                        String missingCode = DBUIUtils
125                                                                                                                        .findNodeValue(
126                                                                                                                                        missingcodeNode,
127                                                                                                                                        MISSINGVALUECODE);
128                                                                                                        // System.out.println("the missing value code add to vector "+missingCode);
129                                                                                                        missingValueCodeVector
130                                                                                                                        .add(missingCode);
131                                                                                                }
132                                                                                        }
133                                                                                }
134
135                                                                                String keyType = DBUIUtils
136                                                                                                .findAttrValue(field, "keyType");
137                                                                                if (keyType != null) {
138                                                                                        if (keyType
139                                                                                                        .equals(KEY_DESC[DSTableKeyIFace.PRIMARYKEY])) {
140                                                                                                tableDef.addPrimaryKey(fldName,
141                                                                                                                dataType,
142                                                                                                                missingValueCodeVector);
143                                                                                        } else if (keyType
144                                                                                                        .equals(KEY_DESC[DSTableKeyIFace.SECONDARYKEY])) {
145                                                                                                tableDef.addSecondaryKey(
146                                                                                                                fldName, dataType,
147                                                                                                                missingValueCodeVector);
148                                                                                        } else {
149                                                                                                tableDef.addField(fldName,
150                                                                                                                dataType,
151                                                                                                                missingValueCodeVector);
152                                                                                        }
153                                                                                } else {
154                                                                                        tableDef.addField(fldName,
155                                                                                                        dataType,
156                                                                                                        missingValueCodeVector);
157                                                                                }
158                                                                        }
159                                                                }
160                                                        }
161                                                } else {
162                                                        System.out
163                                                                        .println("*** Error table DOM node is missing its name!");
164                                                        return null;
165                                                }
166                                        } else {
167                                                System.out
168                                                                .println("*** Error chiuld of schema is not \"table\"!");
169                                                return null;
170                                        }
171                                }
172                        }
173                }
174                return schemaDef;
175        }
176
177        /**
178         * Reads in a Schema Definition and returns a DSSchemaIFace object
179         * 
180         * @param aFileName
181         *            Name of XML file representing a XML document
182         * @return the DSSchemaIFace object
183         */
184        public static DSSchemaIFace readSchemaDef(String aFileName) {
185
186                DSSchemaIFace schemaDef = null;
187                try {
188                        schemaDef = processDOM(DBUIUtils.readXMLFile2DOM(aFileName));
189                        // Debug
190                        /*
191                         * if (schemaDef != null) {
192                         * System.out.println("[\n"+emitXML(schemaDef)+"\n]\n"); }
193                         */
194                } catch (Exception e) {
195                        System.err.println(e);
196                }
197
198                return schemaDef;
199        }
200
201        /**
202         * Parses an XML String representing a Schema Def and returns a
203         * DSSchemaIFace object
204         * 
205         * @param aXMLSchemaStr
206         *            String representing a XML document
207         * @return the DSSchemaIFace object
208         */
209        public static DSSchemaIFace parseSchemaDef(String aXMLSchemaStr) {
210
211                DSSchemaIFace schemaDef = null;
212                try {
213                        // System.out.println("the schema string is "+aXMLSchemaStr);
214                        schemaDef = processDOM(DBUIUtils.convertXMLStr2DOM(aXMLSchemaStr));
215                        // Debug
216                        /*
217                         * if (schemaDef != null) {
218                         * System.out.println("[\n"+emitXML(schemaDef)+"\n]\n"); }
219                         */
220                } catch (Exception e) {
221                        System.err.println(e);
222                }
223
224                return schemaDef;
225        }
226
227        /**
228         * Generate XML for a field schema
229         * 
230         * @param aStrBuf
231         *            the buffer to append to
232         * @param aField
233         *            the objec to be emitted
234         */
235        protected static void emit(StringBuffer aStrBuf, DSTableFieldIFace aField) {
236                if (aField != null) {
237                        aStrBuf.append("    <field name=\"" + aField.getName() + "\"");
238                        aStrBuf.append(" dataType=\"" + aField.getDataType() + "\"");
239                        if (aField instanceof DSTableKeyIFace
240                                        && ((DSTableKeyIFace) aField).getKeyType() != DSTableKeyIFace.UNDEFINEDKEY) {
241                                aStrBuf.append(" keyType=\""
242                                                + KEY_DESC[((DSTableKeyIFace) aField).getKeyType()]
243                                                + "\"");
244                        }
245                        Vector missingValueVector = aField.getMissingValueCode();
246                        if (missingValueVector != null && !missingValueVector.isEmpty()) {
247                                aStrBuf.append(">\n");
248                                aStrBuf.append("       <" + MISSINGVALUELIST + ">\n");
249                                for (int i = 0; i < missingValueVector.size(); i++) {
250                                        String code = (String) missingValueVector.elementAt(i);
251                                        aStrBuf.append("           <" + MISSINGVALUECODE + ">");
252                                        aStrBuf.append(code);
253                                        aStrBuf.append("</" + MISSINGVALUECODE + ">\n");
254                                }
255                                aStrBuf.append("       </" + MISSINGVALUELIST + ">\n");
256                                aStrBuf.append("    </field>\n");
257                        } else {
258                                aStrBuf.append("/>\n");
259                        }
260                }
261        }
262
263        /**
264         * Generate XML for the schema
265         * 
266         * @param aSchema
267         *            the schema
268         * @return string of the schema's xml representation
269         */
270        public static String emitXML(DSSchemaIFace aSchema) {
271                if (aSchema == null)
272                        return "";
273
274                StringBuffer strBuf = new StringBuffer("<schema>\n");
275
276                Vector tables = aSchema.getTables();
277                if (tables != null && tables.size() > 0) {
278                        for (Enumeration et = tables.elements(); et.hasMoreElements();) {
279                                DSTableIFace table = (DSTableIFace) et.nextElement();
280                                strBuf.append("  <table name=\"" + table.getName() + "\">\n");
281                                Vector fields = table.getFields();
282                                for (Enumeration ef = fields.elements(); ef.hasMoreElements();) {
283                                        DSTableFieldIFace field = (DSTableFieldIFace) ef
284                                                        .nextElement();
285                                        emit(strBuf, field);
286                                }
287                                strBuf.append("  </table>\n");
288                        }
289                }
290                strBuf.append("</schema>\n");
291
292                return strBuf.toString();
293        }
294
295}