Package net.xoetrope.optional.data.pojo

Source Code of net.xoetrope.optional.data.pojo.XPojoDataSource

package net.xoetrope.optional.data.pojo;

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.resources.XProjectClassLoader;
import net.xoetrope.xml.XmlElement;
import net.xoetrope.xui.XProject;
import net.xoetrope.xui.build.BuildProperties;
import net.xoetrope.xui.data.XModel;
import net.xoetrope.xui.helper.ReflectionHelper;

/**
* <p>A data source for working with POJOs. When the application is loaded the
* datasources are instantiated and in the case of a XPojoDataSource the
* XPojoRoot instance specified by the <code>root</code> element is
* instantiated and configured. The configuration project involves traversing
* the class hierarchy and setting up XPojoModel nodes or proxies for each class
* in the pojo hierarchy. The configuration can specify naming overrides if the
* names established by reflection are not suitable</p>
* <p>Copyright (c) Xoetrope Ltd., 2001-2007<br>
* License:      see license.txt
*/
public class XPojoDataSource extends XDataSource
{
  protected XPojoContext pojoContext;
  protected XModel pojoRootModel;
  protected Hashtable overrides;
  protected Hashtable adapters;
 
  /**
   * Creates a new instance of XPojoDataSource
   * @param project the owner project
   */
  public XPojoDataSource( XProject project )
  {
    super( project );
    overrides = new Hashtable();
    adapters = new Hashtable();
  }
 
  /**
   * Returns the pojo context object
   * @return pojo context
   */
  public XPojoContext getPojoContext()
  {
    return pojoContext;
  }
 
  /**
   * Creates and returns new XPojoContext object
   * @param className the name of the class whose instance
   * should be returned  
   * @param classLoader class loader object to load the
   * specified class definition
   * @return XPojoContext object
   */
  protected XPojoContext instantiatePojoContext( String className, ClassLoader classLoader )
  throws Exception
  {
    Object pojoContext = null;
    if ( classLoader != null )
      pojoContext = Class.forName( className, true, classLoader ).newInstance();
    else
      pojoContext = Class.forName( className ).newInstance();   
       
    return (XPojoContext)pojoContext;
  }
 
  /**
   * Recursively load the model data
   * @param source the source element
   * @param model the model for the source element
   */
  public void loadTable( XmlElement source, XModel model )
  {
    try {
      // Setup the pojo context
      XmlElement contextElement = source.getFirstChildNamed( "context" );
      String contextClassName = contextElement.getAttribute( "class" );
      String configFileName = contextElement.getAttribute( "config" );     
     
      XProjectClassLoader classLoader = (XProjectClassLoader)currentProject.getProjectClassLoader();
      pojoContext = instantiatePojoContext( contextClassName, classLoader );
      pojoContext.setProject( currentProject );
      currentProject.setObject( "PojoContext", pojoContext ); //???
      if ( configFileName != null )
        pojoContext.configure( currentProject.findResource( configFileName ));       
   
      // Load the customizations of the POJO classes     
      XmlElement overridesElement = source.getFirstChildNamed( "overrides" );
      if ( overridesElement != null ) {
        Vector overrideSpecs = overridesElement.getChildren();
        int numOverrides = overrideSpecs.size();
        for ( int i = 0; i < numOverrides; i++ ) {
          XmlElement overrideElement = (XmlElement)overrideSpecs.elementAt( i );
          String pojoClassName = overrideElement.getAttribute( "class" );               
          overrides.put( pojoClassName, overrideElement );
        }
      }
     
      // Setup the POJO root
      Object pojoRoot = null;
      XmlElement rootElement = source.getFirstChildNamed( "root" );     
      String pojoRootName = "pojo";
      if ( rootElement != null ) {
        String rootClassName = rootElement.getAttribute( "class" );
        pojoRootName = rootElement.getAttribute( "id" );
        configFileName = rootElement.getAttribute( "config" );
        int numParams = rootElement.getChildren().size();       
        if ( numParams == 0 ) {
          if ( classLoader != null )
            pojoRoot = Class.forName( rootClassName.trim(), true, classLoader ).newInstance();
          else
            pojoRoot = Class.forName( rootClassName.trim() ).newInstance();
        }
        else {
          Class[] params = new Class[ numParams ];
          Object[] values = new Object[ numParams ];
          for ( int i = 0; i < numParams; i++ ) {
            XmlElement paramElement = (XmlElement)rootElement.getChildren().elementAt( i );
            String paramType = paramElement.getAttribute( "class" );
            params[ i ] = ReflectionHelper.getParamClass( paramType );
            values[ i ] = ReflectionHelper.getObject( paramType, paramElement.getAttribute( "value" ));
          }
          Class klass = null;
          if ( classLoader != null )
            klass = Class.forName( rootClassName.trim(), true, classLoader );
          else
            klass = Class.forName( rootClassName.trim() );
          pojoRoot = ReflectionHelper.constructViaReflection( klass, params, values );         
        }
       
        if ( pojoRoot instanceof XPojoRoot ) {
          ((XPojoRoot)pojoRoot).setProject( currentProject );
          if ( configFileName != null )
            ((XPojoRoot)pojoRoot).configure( currentProject.findResource( configFileName ));
        }               
      }
      else {
        pojoRoot = pojoContext.getRoot();
      }
     
      // Attach the POJO topology. No need to scan the topology as nodes are
      // adapted on demand                 
      pojoRootModel = createPojoModel( model, pojoRoot );
      ((XPojoModel)pojoRootModel).setId( pojoRootName );
      model.append( (XModel)pojoRootModel );     
    }
    catch ( Exception ex ) {
      DebugLogger.logError( "Failed to load the POJO datasource" );
      if ( BuildProperties.DEBUG )
        ex.printStackTrace();
    }
  }
         
  public XPojoAdapter getAdapter( Object pojo )
  {
    Class pojoClass = pojo.getClass();
    XPojoAdapter adapter = null;
    // check whether the class of the given POJO requires an adapter
    if ( XPojoHelper.needsAdapter( pojoClass )) {
      String pojoClassName = pojoClass.getName();
      adapter = (XPojoAdapter)adapters.get( pojoClassName );
      if ( adapter == null ) {
        adapters.put( pojoClassName, adapter = createAdapter( pojoClass ));
        overrideAdapter( adapter );
      }
    }
    return adapter;
  }
 
  /**
   * Creates and returns a new instance of <code>XPojoAdapter</code>
   * @param pojoClass pojoClass class to be adapted
   * by the returned adapter
   * @return XPojoAdapter object
   */
  protected XPojoAdapter createAdapter( Class pojoClass )
  {       
    return ( new XPojoAdapter( pojoClass, this ));
  }
 
  /**
   * Creates and returns a new instance of <code>XPojoModel</code>
   * @param parent the parent model of the node
   * which is to be created
   * @param subpath String consisting of pojo properties,
   * which must be in the format: propertyName(arguments...)[idx]
   * @return XPojoModel object
   */
  protected XPojoModel createPojoModel( XModel parent, String subPath )
  {
    return ( new XPojoModel( parent, subPath, this ));
  }
 
  /**
   * Creates and returns a new instance of <code>XPojoModel</code>
   * @param parent the parent model node
   * @pojo the underlying pojo
   * @return XPojoModel object
   */
  protected XPojoModel createPojoModel( XModel parent, Object pojo )
  {
    return ( new XPojoModel( parent, pojo, this ));
  }
 
  /**
   * Gets the xml element describing overrides of the class
   * being adapted by the specified adapter.
   * @param adapter the adapter object
   * @return XmlElement object describing the overrides.
   */
  protected XmlElement getOverrideXml( XPojoAdapter adapter )
  {
    String className = adapter.getAdapterClassName();
    return (XmlElement)overrides.get( className );
  }
 
  /**
   * Override the adapter specification loaded via reflection and add the
   * customization specified by the configuration
   * @param adapter the adapter being customized
   */   
  protected void overrideAdapter( XPojoAdapter adapter )
  {
    XmlElement override = getOverrideXml( adapter );
    if ( override != null ) {
      Enumeration enumOverrides = override.getChildren().elements();
      while ( enumOverrides.hasMoreElements() ) {
        XmlElement propertyElement = (XmlElement)enumOverrides.nextElement();
        customizeProperty( adapter, propertyElement );
      }
    }
  }   
 
  /*
   * Customizes given property, saves customization details in
   * the given adapter object.
   * @param adapter the adapter of the class whose property
   * is to be customized.
   * @param propertyElement the xml element describing the customization details.
   */
  protected void customizeProperty( XPojoAdapter adapter, XmlElement propertyElement )
  {
    String elementName = propertyElement.getName();
    if ( "property".equals( elementName )) {   
      String propertyName = propertyElement.getAttribute( "id" );
      String getterSig = propertyElement.getAttribute( "getter" );
      String setterSig = propertyElement.getAttribute( "setter" );
      adapter.customizeProperty( propertyName, getterSig, setterSig );
    }
    else if ( "transient_property".equals( elementName )) {
      String propertyName = propertyElement.getAttribute( "id" );
      adapter.setTransient( propertyName );
    }
  }
              
}

TOP

Related Classes of net.xoetrope.optional.data.pojo.XPojoDataSource

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.