Package net.xoetrope.optional.data

Source Code of net.xoetrope.optional.data.XOptionalDataSource

package net.xoetrope.optional.data;

import java.io.Reader;
import java.io.StringWriter;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;

import net.xoetrope.data.XDataSource;
import net.xoetrope.debug.DebugLogger;
import net.xoetrope.optional.data.sql.DatabaseTableModel;
import net.xoetrope.optional.data.sql.NamedConnectionManager;
import net.xoetrope.optional.service.XRouteManager;
import net.xoetrope.os.LibraryLoader;
import net.xoetrope.optional.service.XServiceModelNode;
import net.xoetrope.optional.service.XServiceProxyNotFoundException;
//import net.xoetrope.xlib.plugin.dialog.XLibDataChooser;
import net.xoetrope.xml.XmlElement;
import net.xoetrope.xml.XmlSource;
import net.xoetrope.xui.XProject;
import net.xoetrope.xui.build.BuildProperties;
import net.xoetrope.xui.data.XModel;
import net.xoetrope.optional.data.sql.DatabaseTable;
import net.xoetrope.xui.helper.ReflectionHelper;

/**
* <p>An extended datasource for handling databses, services and routing</p>
* <p>Copyright: Copyright Xoetrope Ltd. (c) 2003</p>
* $Revision: 2.15 $
* License: see license.txt
*/
public class XOptionalDataSource extends XDataSource
  protected XRouteManager routeMgr;
  protected XDataModelLoader modelLoader;

  /**
   * @param project the owner project
   */
  public XOptionalDataSource( XProject project )
  {
    super( project );
    XOptionalBindingFactory.register( project );

    String caseSensisitive =  currentProject.getStartupParam( "CaseSensitiveDatabase" );
    if (( caseSensisitive != null ) && caseSensisitive.toLowerCase().equals( "false" ))
      DatabaseTable.setCaseSensitive( false );
   
    // default way to build data sources via reflection
    modelLoader = ( new XDataModelLoader() {
      public void loadModel( String className, XmlElement src, XModel model ) {
        Object[] values = new Object[ 1 ];
        values[ 0 ] = currentProject;
        XDataSource dataSource = (XDataSource)ReflectionHelper.constructViaReflection( className, values );
        dataSource.loadTable( src, model );       
      }
    });       
  }

  /**
   * Gets the object being used to load the model node
   * @return XDataModelLoader object
   */
  public XDataModelLoader setModelLoader()
  {
    return modelLoader;
  }
 
  /**
   * Sets the object that is used to construct data sources via relfection.  
   * @param rc the XDataModelLoader object
   */
  public void setModelLoader( XDataModelLoader rc )
  {
    modelLoader = rc;
  }
 
  /**
   * If the ShowVisualiser property is set to true then show the visualiser
   * for debugging
   */
  protected void showVisualisation()
  {
    String sp = currentProject.getStartupParam( "ShowVisualiser" );
    if ( ( sp != null ) && ( sp.compareTo( "true" ) == 0 ) ) {
      String className = currentProject.getStartupParam( "VisualiseClass" );
      try {
        XModelVisualiser visualiser = (XModelVisualiser)Class.forName( className.trim() ).newInstance();
        visualiser.showDlg( "" );
      }
      catch ( Exception ex ) {
        ex.printStackTrace();
      }
    }
  }

  /**
   * Read a model from the Reader
   * @param r the Reader
   */
  public void read( Reader r )
  {
    XmlElement ele = XmlSource.read( r );
    XmlElement dbSrc = null, routeSrc = null, serviceSrc = null;
    Vector v = ele.getChildren();
    if ( v != null ) {
      int numFiles = v.size();
      XModel model = currentProject.getModel();
      for ( int i = 0; i < numFiles; i++ ) {
        try {
          XmlElement source = ( XmlElement )v.elementAt( i );
          Reader sr = currentProject.getBufferedReader( source.getAttribute( "filename" ), "UTF8" );
          if ( sr == null )
            continue;

          if ( BuildProperties.DEBUG )
            DebugLogger.trace( "Datasource: " + source.getAttribute( "filename" ) );

          XmlElement src = XmlSource.read( sr );
          String type = source.getAttribute( "type" );
          if (( type == null ) || ( type.length()==0 ))
            loadTable( src, model );
          else if ( type.equals( "database" ))
            dbSrc = src;
          else if ( type.equals( "routing" ))
            routeSrc = src;
          else if ( type.equals( "service" ))
            serviceSrc = src;
          else if ( modelLoader != null )
            modelLoader.loadModel( type, src, model );
         
          registerDataSource( source );
        }
        catch ( Exception ex ) {
          if ( BuildProperties.DEBUG )
            DebugLogger.logError( "Failed to read configuration file" );
          ex.printStackTrace();
        }
      }

      try {
        if ( routeSrc != null )
          loadRoutes( routeSrc, model );
      }
      catch ( Exception ex1 ) {
        if ( BuildProperties.DEBUG )
          DebugLogger.logError( "Failed to read routes config file" );
      }

      try {
        if ( serviceSrc != null )
          loadService( serviceSrc, model );
      }
      catch ( Exception ex1 ) {
        if ( BuildProperties.DEBUG )
          DebugLogger.logError( "Failed to read services config file" );
      }

      try {
        if ( dbSrc != null ) {
          loadDatabase( dbSrc, model );
        }
      }
      catch ( Exception ex1 ) {
        if ( BuildProperties.DEBUG )
          DebugLogger.logError( "Failed to read database config file" );
      }
    }
    showVisualisation();
  }

  // Design time methods.
  /**
   * Register the datasource files found within the datasets.xml file
   * @param source The path to the discovered file
   */
  public void registerDataSource( XmlElement source ){}
 
  /**
   * Register a database source element found within the datasets.xml file
   * @param source The path to the database file
   */
  public void registerDatabaseNode( XmlElement source ){}

  /**
   * Recursively load the model data
   * @param source the source element
   * @param model the model for the source element
   */
  public void loadDatabase( XmlElement source, XModel model )
  {
    XmlElement connEle = source.elementAt( 0 );
    String dbDriver = connEle.getAttribute( "driver" );
    String dbUrl = connEle.getAttribute( "url" );
    dbUrl = checkLocalHsqldb( dbDriver, dbUrl );

    NamedConnectionManager connMgr = ( NamedConnectionManager )NamedConnectionManager.getInstance();
    connMgr = ( NamedConnectionManager )connMgr.reset( connEle.getAttribute( "id" ),
        dbDriver,
        dbUrl,
        connEle.getAttribute( "user" ),
        connEle.getAttribute( "pwd" ) );

    registerDatabaseNode( connEle );
    Vector vRS = source.getChildren();
    int rsCount = vRS.size();
    int numChildren = model.getNumChildren();
    numChildren += rsCount;
    model.setNumChildren( numChildren );
    for ( int i = 1; i < rsCount; i++ ) {
      XmlElement rsEle = ( XmlElement )vRS.elementAt( i );
      if ( rsEle.getName().compareTo( "Connection" ) == 0 ) {
        String extraDbDriver = rsEle.getAttribute( "driver" );
        String extraDbUrl = rsEle.getAttribute( "url" );
        extraDbUrl = checkLocalHsqldb( extraDbDriver, extraDbUrl );
        connMgr.addConnection( rsEle.getAttribute( "id" ),
                               extraDbDriver,
                               extraDbUrl,
                               rsEle.getAttribute( "user" ),
                               rsEle.getAttribute( "pwd" ) );
      }
      else {
        DatabaseTableModel tableModel = new DatabaseTableModel( currentProject );
        String escapeStr = rsEle.getAttribute( "escape" );
        if ( escapeStr != null )
          tableModel.setDoesEscapeProcessing( "true".equals( escapeStr ));
       
        tableModel.setName( rsEle.getAttribute( "id" ) );
        boolean updateDb = false;
        String updateStr = rsEle.getAttribute( "update" );
        if ( updateStr != null )
          updateDb = updateStr.compareTo( "true" ) == 0;

        String sqlStr = rsEle.getAttribute( "sql" );
        if (( sqlStr != null ) && ( sqlStr.length() > 0 ))
          tableModel.setSqlStatement( sqlStr, rsEle.getAttribute( "conn" ), updateDb );
        else {
            // We should probably change the name table to from as it equates to the FROM clause
          tableModel.setupTable( rsEle.getAttribute( "from" ),
                                 rsEle.getAttribute( "fields" ),
                                 rsEle.getAttribute( "where" ),
                                 rsEle.getAttribute( "conn" ),
                                 updateDb );
          String distinctStr = rsEle.getAttribute( "distinct" );
          if ( distinctStr != null )
            tableModel.setDistinct( distinctStr.equals( "true" ));

          tableModel.setOrderField( rsEle.getAttribute( "order" ) );
        }
        model.append( tableModel );
      }
      registerDatabaseNode( rsEle );
    }
  }

  /**
   * Check for a local database url. For hsqldb this extracts the db files to a
   * local directory and returns the modiefied URL
   * @param dbDriver the database drivr class
   * @param dbUrl the database url
   */
  protected String checkLocalHsqldb( String dbDriver, String dbUrl )
  {
    return checkLocalHsqldb( getClass().getClassLoader(), dbDriver,  dbUrl );
  }
 
  /**
   * Check for a local database url. For hsqldb this extracts the db files to a
   * local directory and returns the modiefied URL
   * @param cl teh classloader used to try and find the database files
   * @param dbDriver the database drivr class
   * @param dbUrl the database url
   */
  public static String checkLocalHsqldb( ClassLoader cl, String dbDriver, String dbUrl )
  {
    if ( dbDriver.equals( "org.hsqldb.jdbcDriver" )) {
      if ( dbUrl.indexOf( '.' ) < 0 ) {
        String dbName = dbUrl.substring( dbUrl.lastIndexOf( ':' ) + 1 );
        try {
          String fileName = cl.getResource( dbName + ".script" ).getFile();
          /** @todo check that the file is not already extracted, up-to-date and in use. */
          if ( fileName.indexOf( ".jar" ) > 0 ) {
            fileName = LibraryLoader.extractFile( cl, dbName + ".script" );
            LibraryLoader.extractFile( cl, dbName + ".properties" );
            LibraryLoader.extractFile( cl, dbName + ".data" );
          }
          return dbUrl.substring( 0, dbUrl.lastIndexOf( ':' ) + 1 ) + fileName.substring( 0, fileName.lastIndexOf( '.' ) );
        }
        catch ( Exception ex ) {
          if ( BuildProperties.DEBUG )
            DebugLogger.logWarning( "Unable to open the resource file: " + dbName + ".script" );
        }
      }
    }
    return dbUrl;
  }

  /**
   * Recursively load the model data
   * @param source the source element
   * @param model the model for the source element
   */
  public void loadService( XmlElement source, XModel model )
  {
    routeMgr = XRouteManager.setupRouteManager( currentProject );

    // Get the 'Services' node
    Vector serviceNodes = source.getChildren();

    // iterate all of the 'service' children
    int serviceCount = serviceNodes.size();
    for ( int i = 0; i < serviceCount; i++ ) {
      XmlElement eleService = ( XmlElement )serviceNodes.elementAt( i );
      String serviceName = eleService.getAttribute( "id" );
      if ( BuildProperties.DEBUG ) {
        if ( serviceName == null )
          DebugLogger.logWarning( "Service (" + i + ") id is null or missing" );
      }
      String serviceRoute = eleService.getAttribute( "route" );
      String serviceImplementationClass = eleService.getAttribute( "server" );
//      int argSize = eleService.getChildren().size();

      // iterate the 'arg' and 'return' elements of the service
      /*
       * This is removed for now as it really wasn't doing anything. We should re-introduce it
       * but flag the arguments as private or public. If private then only the layer's owner can
       * modify the argument.
      String[] args = new String[ argSize ];
      for ( int argNode = 0; argNode < argSize; argNode++ ) {
        // Get the type of all args and only the type of the 'return' element.
        String argName, argType;
        XmlElement argEle = eleService.elementAt( argNode );
        argType = argEle.getAttribute( "type" );
        if ( argEle.getName().compareTo( "arg" ) == 0 ) {
          argName = argEle.getAttribute( "id" );
          args[ argNode ] = argName;
        }
      }*/
      String[] args = new String[ 0 ];

      XServiceModelNode node = new XServiceModelNode();
      try {
        node.setupService( serviceName, routeMgr.getRoute( serviceRoute, serviceImplementationClass ), args );
        node.getServiceProxy().setServiceName( serviceName );
        model.set( serviceName, node );
      }
      catch ( XServiceProxyNotFoundException ex ) {
        ex.printStackTrace();
      }
    }
  }

  /**
   * Load the routing information
   * @param source the source element
   * @param model the model for the source element
   */
  public void loadRoutes( XmlElement source, XModel model )
  {
    // Initialise the XRouteManager
    XRouteManager routeMgr = ((XRouteManager)currentProject.getObject( "RouteMgr" ));
    if ( routeMgr == null ) {
      routeMgr = new XRouteManager( currentProject );
      currentProject.setObject( "RouteMgr", routeMgr );
    }

    Vector routeNodes = source.getChildren();

    // iterate all of the 'route' children
    int routeCount = routeNodes.size();
    for ( int i = 0; i < routeCount; i++ ) {
      XmlElement routeElement = ( XmlElement )routeNodes.elementAt( i );
      String routeName = routeElement.getAttribute( "id" );
      if ( routeName == null )
        continue;

      // For each route add the layers
      int layerCount = routeElement.getChildren().size();
      Hashtable[] layers = new Hashtable[ layerCount ];
      for ( int layer = 0; layer < layerCount; layer++ ) {
        XmlElement layerElement = routeElement.elementAt( layer );
        Hashtable layerTable = new Hashtable();

        // Put any extra attributes into a hashtable
        Enumeration attribs = layerElement.enumerateAttributeNames();
        while ( attribs.hasMoreElements() ) {
          String attribName = attribs.nextElement().toString();
          layerTable.put( attribName, layerElement.getAttribute( attribName ) );

          // Add the children of the layer node
          int pathCount = layerElement.getChildren().size();
          for ( int pathIdx = 0; pathIdx < pathCount; pathIdx++ ) {
            XmlElement pathElement = layerElement.elementAt( pathIdx );
            Vector pathTable = new Vector();

            // Put any extra path attributes into a hashtable
            Enumeration pathAttribs = pathElement.enumerateAttributeNames();
            while ( pathAttribs.hasMoreElements() ) {
              String pathAttribName = (String)pathAttribs.nextElement();
              if ( pathAttribName.compareTo( "id" ) == 0 )
                pathTable.add( pathElement.getAttribute( "id" ) );
              else
                ; // do nothing with the extra data for now.
            }

            layerTable.put( new Integer( pathIdx ).toString(), pathTable );
          }
        }
        layers[ layer ] = layerTable;

      }
      // add the route to the XRouteManager
      routeMgr.addRoute( routeName, layers );
    }
  }
  /**
   * Output the model to a String and return it
   * @param mdl the model to bt output
   * @return the String representation of the model
   */
  public String getModelXML( XModel mdl )
  {
    StringWriter sw = new StringWriter();
    super.outputModel( sw, mdl );
    return sw.toString();
  }
 
}
TOP

Related Classes of net.xoetrope.optional.data.XOptionalDataSource

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.