org.kepler.dataproxy.datasource.geon.GEONDatabaseResource.java Source code

Java tutorial

Introduction

Here is the source code for org.kepler.dataproxy.datasource.geon.GEONDatabaseResource.java

Source

/*
 * Copyright (c) 2003-2010 The Regents of the University of California.
 * All rights reserved.
 *
 * '$Author: welker $'
 * '$Date: 2010-05-05 22:21:26 -0700 (Wed, 05 May 2010) $' 
 * '$Revision: 24234 $'
 * 
 * Permission is hereby granted, without written agreement and without
 * license or royalty fees, to use, copy, modify, and distribute this
 * software and its documentation for any purpose, provided that the above
 * copyright notice and the following two paragraphs appear in all copies
 * of this software.
 *
 * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
 * FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
 * THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
 * PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
 * CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
 * ENHANCEMENTS, OR MODIFICATIONS.
 *
 */

package org.kepler.dataproxy.datasource.geon;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URL;
import java.sql.DriverManager;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xpath.XPathAPI;
import org.ecoinformatics.seek.datasource.EcogridMetaDataCacheItem;
import org.ecoinformatics.seek.ecogrid.quicksearch.ResultTreeRoot;
import org.ecoinformatics.seek.querybuilder.DBQueryDef;
import org.geon.DatabaseQuery;
import org.kepler.configuration.ConfigurationManager;
import org.kepler.configuration.ConfigurationProperty;
import org.kepler.dataproxy.datasource.DataSourceInterface;
import org.kepler.dataproxy.metadata.ADN.ADNMetadataSpecification;
import org.kepler.objectmanager.cache.DataCacheListener;
import org.kepler.objectmanager.cache.DataCacheManager;
import org.kepler.objectmanager.cache.DataCacheObject;
import org.kepler.objectmanager.data.DataSourceControllerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import ptolemy.actor.gui.style.TextStyle;
import ptolemy.data.BooleanToken;
import ptolemy.data.expr.SingletonParameter;
import ptolemy.kernel.CompositeEntity;
import ptolemy.kernel.util.IllegalActionException;
import ptolemy.kernel.util.NameDuplicationException;
import ptolemy.kernel.util.Settable;
import ptolemy.kernel.util.StringAttribute;
import ptolemy.vergil.icon.EditorIcon;
import ptolemy.vergil.kernel.attributes.EllipseAttribute;
import ptolemy.vergil.kernel.attributes.ResizablePolygonAttribute;
import ptolemy.vergil.kernel.attributes.TextAttribute;

/**
 * An actor that serves as a proxy to query a specific database (defined by geon
 * id).
 */
public class GEONDatabaseResource extends DatabaseQuery implements DataCacheListener, DataSourceInterface {

    private static final String SCHEMAENTITY = "//databaseMetaData/schema";
    private static final String TABLEENTITY = "//databaseMetaData/schema/table";
    private static final String VIEWENTITY = "//databaseMetaData/schema/view";
    private static final String SCHEMANAMEATT = "name";
    private static final String TABLENAMEATT = "name";
    private static final String FIELDTAG = "column";
    private static final String FIELDATT = "name";
    private static final String FIELDDATATYPE = "datatype";
    private static final String FIELDSIZE = "size";
    private static final String FIELDRESTRICTION = "nullable";

    private static final String EMAILPATH = "//sqlEngine[sqlEngineName=\"geon\"]/email";
    private static final String USERNAMEPATH = "//sqlEngine[sqlEngineName=\"geon\"]/userName";
    private static final String DRIVERPATH = "//sqlEngine[sqlEngineName=\"geon\"]/dbDriver";
    private static final String JDBCCONNECTPATH = "//sqlEngine[sqlEngineName=\"geon\"]/jdbcConnect";

    private DataSourceControllerFactory _nodeController = null;

    // /////////////////////////////////////////////////////////////////
    // // private variables ////

    private DBQueryDef _queryDef = null;

    private EcogridMetaDataCacheItem _cacheMetaDataItem = null;

    // /////////////////////////////////////////////////////////////////
    // // private variables ////

    /** Icon indicating the communication region. */
    protected EllipseAttribute _elli;
    protected ResizablePolygonAttribute _rect;
    protected TextAttribute _text;

    // /////////////////////////////////////////////////////////////////
    // // ports and parameters ////

    public StringAttribute _idAtt = null;

    public StringAttribute _endpointAtt = null;

    public StringAttribute _namespaceAtt = null;

    public StringAttribute _descriptionAtt = null;

    public SingletonParameter hideCon;

    public SingletonParameter _hideNS;

    protected final static Log log;
    static {
        log = LogFactory.getLog("org.kepler.dataproxy.datasource.geon.GEONDatabaseResource");
    }

    /**
     * Construct an actor with the given container and name.
     * 
     * @param container
     *            The container.
     * @param name
     *            The name of this actor.
     * @exception IllegalActionException
     *                If the actor cannot be contained by the proposed
     *                container.
     * @exception NameDuplicationException
     *                If the container already has an actor with this name. s * @since
     */
    public GEONDatabaseResource(CompositeEntity container, String name)
            throws NameDuplicationException, IllegalActionException {
        super(container, name);

        TextStyle queryDefTS = new TextStyle(query, "query");

        hideCon = new SingletonParameter(dbcon, "_hide");
        hideCon.setToken(BooleanToken.TRUE);

        // _sqlAttr = new StringAttribute(this, "sqlDef");
        // _sqlAttr.setVisibility(Settable.NONE);
        // TextStyle sqlDefTS = new TextStyle(_sqlAttr, "sqlDef");

        _idAtt = new StringAttribute(this, RECORDID);
        _idAtt.setVisibility(Settable.NOT_EDITABLE);

        _endpointAtt = new StringAttribute(this, ENDPOINT);
        _endpointAtt.setVisibility(Settable.NOT_EDITABLE);

        _namespaceAtt = new StringAttribute(this, NAMESPACE);
        _namespaceAtt.setVisibility(Settable.NONE);

        _descriptionAtt = new StringAttribute(this, "description");
        // _descriptionAtt.setVisibility(Settable.NOT_EDITABLE);
        TextStyle descTSatt = new TextStyle(_descriptionAtt, "descriptionTS");

        // create tableau for editting the SQL String
        // _qbTableauFactory = new QBTableauFactory(this, "_tableauFactory");

        // Create a node controller to control the context menu
        _nodeController = new DataSourceControllerFactory(this, "_controllerFactory");

        EditorIcon node_icon = new EditorIcon(this, "_icon");

        _rect = new ResizablePolygonAttribute(node_icon, "inner");
        // _rect.rounding.setToken("5.0");
        _rect.vertices.setToken("{-20,0, -20,40, 20,40, 20,0}");
        _rect.width.setToken("40");
        _rect.height.setToken("40");
        _rect.centered.setToken("false");
        _rect.lineColor.setToken(BLACK);

        // Create the folder
        _elli = new EllipseAttribute(node_icon, "outer");
        // _elli.
        // _poly1.vertices.setToken("{7,-27, 7,-8, 28,-10, 28,-27, 16,-27, 15,-29, 7,-29}");
        // _elli.vertices.setToken("{0,0, 8,-2, 9,1, 24,-2, 24,20, 0,24, 0,0}");
        _elli.width.setToken("40");
        _elli.height.setToken("30");
        _elli.centered.setToken("true");
        _elli.lineColor.setToken(BLACK);

        _text = new TextAttribute(node_icon, "text");
        _text.textSize.setExpression("11");

        setIconStatus(TITLE_BINARY, YELLOW);

        node_icon.setPersistent(false);
        /*
         * if (_TypeHash.size() == 0) { for (int i = 0; i < DATATYPES.length;
         * i++) { _TypeHash.put(DATATYPES[i], BASETYPES[i]); } }
         */}

    /**
     * Callback for changes in attribute values.
     */
    public void attributeChanged(ptolemy.kernel.util.Attribute attribute)
            throws ptolemy.kernel.util.IllegalActionException {
        // dbg.print("In attribute change method", 2);
        /*
         * if (attribute == _sqlAttr) { if (_sqlAttr != null &&
         * !_sqlAttr.equals("")) { String sqlXMLStr = ((Settable)
         * _sqlAttr).getExpression(); DBQueryDef queryDef =
         * DBQueryDefParserEmitter.parseQueryDef( _schemaDef, sqlXMLStr); String
         * sqlStr = DBQueryDefParserEmitter.createSQL(_schemaDef, queryDef); if
         * (sqlStr != null) { query.setToken(new StringToken(sqlStr)); } } }
         * else if (attribute == _schemaAttr) { String schemaDef = ((Settable)
         * _schemaAttr).getExpression();
         * 
         * if (schemaDef.length() > 0) { dbg.print("schemaDef >>" + schemaDef +
         * "<<", 2); _schemaDef =
         * DBSchemaParserEmitter.parseSchemaDef(schemaDef); } }
         */
        if ((attribute.getName().equals(RECORDID) || attribute.getName().equals(ENDPOINT))
                // && this.hasConnectionValues()
                && !(attribute.getContainer().getContainer() instanceof ResultTreeRoot)) {
            log.debug("change recorid or endpoints");
            setIconStatus(TITLE_BUSY, RED);
            String _recordId = getRecordId();
            String _endpoint = getEndpoint();
            if (_recordId != null && !_recordId.equals("") && _endpoint != null && !_endpoint.equals("")) {
                _cacheMetaDataItem = (EcogridMetaDataCacheItem) DataCacheManager.getCacheItem(this,
                        "MetaData " + _recordId, _endpoint, EcogridMetaDataCacheItem.class.getName());
                _cacheMetaDataItem.setEndPoint(_endpoint);
                _cacheMetaDataItem.setRecordId(_recordId);
                _cacheMetaDataItem.start();
            }
        } else
            super.attributeChanged(attribute);
    }

    /**
     * Get the database connection.
     * 
     * @throws IllegalActionException
     */
    public void getConnection() throws IllegalActionException {

        ConfigurationManager confMan = ConfigurationManager.getInstance();
        ConfigurationProperty commonProperty = confMan.getProperty(ConfigurationManager.getModule("common"));
        ConfigurationProperty geonSqlEngine = commonProperty.getProperty("sqlEngines")
                .findProperties("sqlEngineName", "geon", true).get(0);

        String dbURL = geonSqlEngine.getProperty("jdbcConnect").getValue() + "/" + getRecordId();

        try {
            Class.forName(geonSqlEngine.getProperty("dbDriver").getValue()).newInstance();
            _db = DriverManager.getConnection(dbURL, geonSqlEngine.getProperty("email").getValue(),
                    geonSqlEngine.getProperty("userName").getValue());
        } catch (Exception e) {
            e.printStackTrace();
            throw new IllegalActionException(this, e, "CONNECTION FAILURE");
        }
    }

    /**
     * Get a URL pointer to the ADN documentation for this data source.
     * 
     * @return URL the URL of the HTML file containing the documentation
     */
    public URL getDocumentation() // TODO:: MODIFY THIS FUNCTION!!!
    {
        try {
            URL htmlDoc = ADNMetadataSpecification.getDocumentation(getRecordId());
            return htmlDoc;
        } catch (Exception ex) {
            return null;
        }
    }

    /**
     * Get the endpoint of this record. The endpoint indicates where the service
     * generating the record can be accessed.
     * 
     * @return endpoint the URL of the service that contains the record
     */
    public String getEndpoint() {
        String value = null;
        try {
            StringAttribute attribute = (StringAttribute) this.getAttribute(ENDPOINT);
            value = attribute.getExpression();
        } catch (Exception e) {
            System.err.println("getEndpoint - ENDPOINT attr is null.");
        }
        return value;
    }

    /**
     * Get the namespace of this record.
     * 
     * @return namespace the URL of the service that contains the record
     */
    public String getNamespace() {
        String value = null;
        try {
            StringAttribute attribute = (StringAttribute) this.getAttribute(NAMESPACE);
            value = attribute.getExpression();
        } catch (Exception e) {
            System.err.println("getNamespace - NAMESPACE attr is null.");
        }
        return value;
    }

    /**
     * Get the identifier of this record.
     * 
     * @return the String that uniquely identifies the record
     */
    public String getRecordId() {
        String value = null;
        try {
            StringAttribute attribute = (StringAttribute) this.getAttribute(RECORDID);
            value = attribute.getExpression();
        } catch (Exception e) {
            System.err.println("getRecordId - RECORDID attr is null.");
        }
        return value;
    }

    /**
     * Creates the schema definition from the cached metadata file
     */
    private void createSchemaFromData(File cachedMetaDataFile) {
        StringBuffer schema = new StringBuffer();
        schema.append("<schema>\n");
        try {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            factory.setValidating(false);
            DocumentBuilder builder = factory.newDocumentBuilder();
            InputStream is = new FileInputStream(cachedMetaDataFile);
            Document doc = builder.parse(is);

            int numTables = 0;

            // NodeList tables = XPathAPI.selectNodeList(doc, TABLEENTITY);
            NodeList schemas = XPathAPI.selectNodeList(doc, SCHEMAENTITY);
            for (int x = 0; x < schemas.getLength(); x++) {
                String schemaName = ((Element) schemas.item(x)).getAttribute(SCHEMANAMEATT);
                NodeList tables = schemas.item(x).getChildNodes();
                for (int i = 0; i < tables.getLength(); i++) {
                    Node child = tables.item(i);
                    if (!(child instanceof Element))
                        continue;
                    // get table name
                    String tableName = ((Element) tables.item(i)).getAttribute(TABLENAMEATT);
                    if (tableName == null || tableName.equals(""))
                        continue; // table with no name
                    else {
                        // get fields
                        if (schemaName != null && !schemaName.equals("") && schemas.getLength() > 1)
                            tableName = schemaName + "." + tableName;
                        StringBuffer table = new StringBuffer();
                        table.append("  <table name=\"" + tableName + "\">\n");
                        int numFields = 0;

                        NodeList fields = ((Element) tables.item(i)).getElementsByTagName(FIELDTAG);
                        for (int j = 0; j < fields.getLength(); j++) {
                            Element field = (Element) fields.item(j);
                            // get field name
                            String fieldName = field.getAttribute(FIELDATT);
                            if (fieldName == null || fieldName.equals(""))
                                continue;
                            else {
                                numFields++;

                                // get field type
                                NodeList datatypes = field.getElementsByTagName(FIELDDATATYPE);
                                String datatype = datatypes.item(0).getFirstChild().getNodeValue();
                                if (datatype == null || datatype.equals(""))
                                    datatype = "UNKNOWN";
                                NodeList fieldsizes = field.getElementsByTagName(FIELDSIZE);
                                String size = fieldsizes.item(0).getFirstChild().getNodeValue();
                                if (size != null && !size.equals(""))
                                    datatype += "(" + size + ")";
                                NodeList constraints = field.getElementsByTagName(FIELDRESTRICTION);
                                String constraint = constraints.item(0).getFirstChild().getNodeValue();
                                if (constraint != null && constraint.trim().toLowerCase().startsWith("no"))
                                    datatype += "  not null";
                                table.append(
                                        "    <field name=\"" + fieldName + "\" dataType=\"" + datatype + "\"/>\n");
                            }
                        }
                        table.append("  </table>\n");
                        if (numFields > 0) {
                            numTables++;
                            schema.append(table.toString());
                        }
                    }
                }
            }
            schema.append("</schema>");
            if (numTables > 0) {
                _schemaAttr.setExpression(schema.toString());
            } else {
                setIconStatus(TITLE_ERROR, MAGENTA);
            }

        } catch (Exception ex) {
            System.out.println("Unable to populate schema: " + ex.getMessage());
        }

    }

    /**
     * Set the text and color of the icon
     * 
     * @param aText
     * @param aColor
     */
    private void setIconStatus(String aText, String aColor) {
        try {
            _text.text.setExpression(aText);
            _elli.fillColor.setToken(aColor);
            _rect.fillColor.setToken(aColor);
        } catch (Exception e) {
        }
    }

    // ------------------------------------------------------------------------
    // -- DataCacheListener
    // ------------------------------------------------------------------------

    public void complete(DataCacheObject aItem) {
        log.debug("complete: " + this);

        aItem.removeListener(this);

        // setIconStatus(TITLE_BUSY, RED);
        if (aItem.isReady()) {

            boolean resultsetWasOK = false;
            try {
                String cachedFileName = aItem.getAbsoluteFileName();
                if (cachedFileName != null && cachedFileName.length() > 0) {
                    File cachedMetaDataFile = new File(cachedFileName);
                    if (cachedMetaDataFile.length() > 0) {
                        createSchemaFromData(cachedMetaDataFile);
                        setIconStatus(TITLE_BINARY, YELLOW);
                    } else {
                        setIconStatus(TITLE_ERROR, MAGENTA);
                        System.err.println("File " + cachedFileName + " is empty.");
                    }
                } else {
                    setIconStatus(TITLE_ERROR, MAGENTA);
                    System.err.println("Cached File Name (LocalName) is null or empty!");
                }
            } catch (Exception e) {
                setIconStatus(TITLE_ERROR, MAGENTA);
            }

            // } else {
            // setIconStatus(TITLE_ERROR, MAGENTA);
        }
    }
}