Package net.xoetrope.registry

Source Code of net.xoetrope.registry.XRegisteredComponentFactory

package net.xoetrope.registry;

import net.xoetrope.xui.XComponentConstructor;
import net.xoetrope.xui.XComponentFactory;
import java.awt.Component;
import java.io.Reader;
import java.io.InputStreamReader;
import java.io.BufferedReader;
import java.net.URL;
import java.util.Enumeration;
import net.xoetrope.debug.DebugLogger;
import net.xoetrope.xml.XmlElement;
import net.xoetrope.xml.XmlSource;
import net.xoetrope.xui.build.BuildProperties;
import java.util.Vector;
import java.util.Hashtable;
import net.xoetrope.xui.XProject;

/**
* <p>A component factory that builds components based upon some XML configuration
* files. This factory is designed to work with the KalIDEoscope which includes a
* graphical utility for selection and configuration of components. The XML
* configuration file may also be manipulated outside of the editor.</p>
* <p>The factory works by reading a file specifying where a component can be
* loaded from and the methods within that component that can be used to get and
* set properties. The getter and setter methods do not need to follow the bean
* specification and can include various arguments and they can also use different
* naming schemes.
* </p>
* <p> Copyright (c) Xoetrope Ltd., 2002-2004</p>
* <p> $Revision: 1.21 $</p>
* <p> License: see License.txt</p>
*/
public class XRegisteredComponentFactory  implements XComponentConstructor
{
  /**
   * The register of component adapters for each component type
   */
  protected Hashtable propertiesRegister;

  /**
   * The config files used to build the set of component adapters
   */
  protected static Hashtable configFiles;

  /**
   * A counter for changes to the registry. Used to indicate if the registry
   * needs to be rebuilt
   */
  protected static int changeCounter;

  /**
   * Used for tracking changes to the registry spec.
   */
  protected int localChangeCounter = -1;

  /**
   * Location/spec of the jar file from which the resource are loaded. A temporary object
   */
  protected String urlBase;
 
  protected XProject currentProject;

  /**
   * Create the new component factory
   * @param project the owner project
   */
  public XRegisteredComponentFactory( XProject project )
  {
    propertiesRegister = new Hashtable();
    if ( BuildProperties.DEBUG )
        DebugLogger.trace( "Setting up XRegisteredComponentFactory" );

    addConfigFile( "XUI", "net/xoetrope/xui/resources/components.xml", false );
    currentProject = project;

    String projectRegistryFile = currentProject.getStartupParam( "ComponentRegistry" );
    if ( ( projectRegistryFile == null ) || ( projectRegistryFile.length() == 0 ) )
     projectRegistryFile = "components";
    if ( projectRegistryFile.indexOf( ".xml" ) < 0 )
      projectRegistryFile += ".xml";

    URL url = currentProject.findResource( projectRegistryFile );
    if ( url != null )
      addConfigFile( "Project", url, false );
  }

  /**
   * Add a configuration file.
   * If the files have already been loaded then the new file will be loaded
   * @param key the name by which the configuration file is referenced
   * @param resource the name/path of the configuration file or the URL for the file
   * @param overwrite true to overwrite and existing entry matching the specified key
   */
  public static void addConfigFile( String key, Object resource, boolean overwrite )
  {
    if ( resource == null )
      return;

    if  ( configFiles == null )
      configFiles = new Hashtable();

    Object resourceObj = configFiles.get( key );
    // If the same file name is already used then ignore it.
    if (( resourceObj != null ) && resource.equals( resourceObj ))
      return;

    changeCounter++;
    if (( resourceObj != null ) || overwrite )
      configFiles.remove( key );

    configFiles.put( key, resource );
  }

  /**
   * Signal that the configuration has been updated.
   */
  public static void updateConfig()
  {
    changeCounter++;
  }


  /**
   * A generic factory for adding XComponents. The component is constructed, positioned and
   * added to the parent panel if one exists. The component is named with a counter value
   * to uniquely identify the control.
   * When a ScrollPane is addd it becomes the parent.
   * @param cf the calling component factory
   * @param type a name identifying the type of component to be created
   * @param content the component text/content
   * @return the new component
   */
  public Object constructComponent( XComponentFactory cf, String type, String content )
  {
    Component comp = null;
    checkRegistration();

    ComponentAdapter componentDescription = (ComponentAdapter)propertiesRegister.get( type );
    if ( componentDescription != null ) {
      try {
        comp = (Component)componentDescription.clazz.newInstance();
        componentDescription.setProperty( comp, "content", content, "String" );
      }
      catch ( IllegalAccessException ex ) {
        ex.printStackTrace();
      }
      catch ( InstantiationException ex ) {
        ex.printStackTrace();
      }
    }
    return comp;
  }

  /**
   * A generic factory method for adding non component elements. The method can
   * be useful in conjunction with the 'repeat' and 'include' keywords where
   * a component may not have a one to one relationship with the XML element.
   * @param cf the calling component factory
   * @param type the object type
   * @param name a name identifying the element to be created
   * @param content the component text/content
   * @param attribs the element attributes if any
   * @return the new component
   */
  public Object addElement( XComponentFactory cf, String type, String name, String content, Hashtable attribs )
  {
    if ( BuildProperties.DEBUG )
      DebugLogger.logWarning( "Unsupported Operation - XEditorRegisteredComponentFactory.addElement(...)" );
    return null;
  }

  /**
   * Notify the component factories that some of their settings may have changed
   */
  public void update()
  {
    if ( BuildProperties.DEBUG )
      DebugLogger.logWarning( "Unsupported Operation - XEditorRegisteredComponentFactory.update()" );
  }

  /**
   * Set the package name for the factory's widgets. This factory ignores the
   * default package name as the classes/componentes being instantiated can come
   * from different packages and their package must be fully specified.
   * @param defPackage the default package name
   */
  public void setPackageName( String defPackage )
  {
    if ( BuildProperties.DEBUG )
      DebugLogger.logWarning( "Unsupported Operation - XEditorRegisteredComponentFactory.setPackageName(...)" );
  }

  /**
   * Get the adapter for a particular component type. The adapter can be used
   * to get and set properties of the component.
   * @param type the name by which the component is specified and referenced
   * @return the adapter
   */
  public ComponentAdapter getComponentAdapter( String type )
  {
    return (ComponentAdapter)propertiesRegister.get( type );
  }

  /**
   * Read the component registry. The format is described in the components.xsd
   * schema.
   */
  protected void read()
  {
    propertiesRegister.clear();

    Enumeration enumeration = configFiles.keys();
    while ( enumeration.hasMoreElements() ) {
      String key = ( String ) enumeration.nextElement();
      if ( !key.equals( "Project" ) )
        doRead( key, configFiles.get( key ) );
    }

    doRead( "Project", configFiles.get( "Project" ) );
  }

  /**
   * Read the component registry. The format is described in the components.xsd
   * schema. The config file is also registered.
   * @param configFile the name of the configuration file
   * @param key the name by which the configuration file is referenced
   */
  protected void read( String key, String configFile )
  {
    addConfigFile( key, configFile, true );
    doRead( key, configFile );
  }

  /**
   * Read the component registry. The format is described in the components.xsd
   * schema.
   * @param configFile the name of the configuration file
   * @param key the name by which the configuration file is referenced
   */
  protected void doRead( String key, Object configFile )
  {
    if ( configFile == null )
      return;
    else if ( configFile instanceof URL )
      doRead( key, (URL)configFile );
    else
      doRead( key, (String)configFile );
  }

  /**
   * Read the component registry. The format is described in the components.xsd
   * schema.
   * @param configFile the name of the configuration file
   * @param key the name by which the configuration file is referenced
   */
  protected void doRead( String key, String configFile )
  {
    if ( BuildProperties.DEBUG )
        DebugLogger.trace( "XRegisteredComponentFactory reading config file: " + configFile );

    try {
      urlBase = "";
      String fileName = configFile;
      if ( fileName.indexOf( ".xml" ) < 0 )
        fileName += ".xml";
      Reader r = currentProject.getBufferedReader( fileName, null );
      if ( r != null )
        read( key, r );
    }
    catch ( Exception ex ) {
        ex.printStackTrace();
    }
  }

  /**
   * Read the component registry. The format is described in the components.xsd
   * schema.
   * @param configFileURL the URL of the configuration file
   * @param key the name by which the configuration file is referenced
   */
  protected void doRead( String key, URL configFileURL )
  {
    if ( BuildProperties.DEBUG )
        DebugLogger.trace( "XRegisteredComponentFactory reading config file: " + configFileURL.toString() );

    try {
      String file = configFileURL.getFile();
      urlBase = file.substring( 0, file.indexOf( '!' ) + 2 );
      Reader r = new BufferedReader( new InputStreamReader( configFileURL.openStream() ));
      if ( r != null )
        read( key, r );
    }
    catch ( Exception ex ) {
        ex.printStackTrace();
    }
  }


  /**
   * Read the component registry. The format is described in the components.xsd
   * schema.
   * @param key the name by which the configuration file is referenced
   * @param reader the reader from which to read the file
   */
  public void read( String key, Reader reader )
  {
    try {
      XmlElement regRoot = XmlSource.read( reader );

      Vector componentNodes = regRoot.getChildren();
      int numComponents = componentNodes.size();
      for ( int i = 0; i < numComponents; i++ ) {
        XmlElement componentNode = ( XmlElement )componentNodes.elementAt( i );
        try {
          String componentName = componentNode.getAttribute( "name" );
          String iconName = componentNode.getAttribute( "icon" );
          String reflect = componentNode.getAttribute( "reflect" );
          String tag = componentNode.getName().toLowerCase();
          if ( !tag.equals( "component" ))
            continue;
          ComponentAdapter oldCa = (ComponentAdapter)propertiesRegister.get( componentName );
          ComponentAdapter ca = oldCa;
          if ( oldCa == null ) {
            if (( reflect != null ) && reflect.equals( "true" )) {
              ca = addReflectionAdapter( key, componentName, iconName, componentNode.getAttribute( "class" ), componentNode.getAttribute( "ui" ));
              // Make sure there aren't duplicates of this property.
              propertiesRegister.remove( componentName );
              propertiesRegister.put( componentName, ca );
              continue;
            }
            ca = addComponentAdapter( key, componentName, iconName, componentNode.getAttribute( "class" ), componentNode.getAttribute( "ui" ));
          }
          Vector propertyNodes = componentNode.getChildren();
          int numProperties = propertyNodes.size();
          for ( int j = 0; j < numProperties; j++ ) {
            XmlElement propertyNode = componentNode.elementAt( j );
            String type = propertyNode.getAttribute( "type" );
            String name = propertyNode.getAttribute( "name" );
            String method = propertyNode.getAttribute( "method" );
            String attribStr = propertyNode.getAttribute( "attrib" );
            boolean attributed = (( attribStr != null ) && ( attribStr.equals( "true" )));
            String paramType = "String";
            if ( type == null )
              type = "both";
           
            if(( name != null ) && ( method != null )){
              if ( type.equals( "get" ) || type.equals( "both" )) {
                String getMethod = method;
                if (( getMethod == null ) || ( getMethod.length() == 0 ))
                  getMethod = "get" + name.substring( 0, 1 ).toUpperCase() + name.substring( 1 );
                else if ( type.equals( "both" ))
                  getMethod = "get" + method.substring( 0, 1 ).toUpperCase() + method.substring( 1 );

                Vector params = propertyNode.getChildren();
                if ( params.size() > 0 )
                  paramType = ((XmlElement)params.elementAt( 0 )).getAttribute( "type" );

                ca.addProperty( "get", name, getMethod, paramType, attributed, true, null );
              }

              if ( type.equals( "set" ) || type.equals( "both" )) {
                String setMethod = method;
                if (( setMethod == null ) || ( setMethod.length() == 0 ))
                  setMethod = "set" + name.substring( 0, 1 ).toUpperCase() + name.substring( 1 );
                else if ( type.equals( "both" ))
                  setMethod = "set" + method.substring( 0, 1 ).toUpperCase() + method.substring( 1 );

                Vector params = propertyNode.getChildren();
                if ( params.size() > 0 )
                  paramType = ((XmlElement)params.elementAt( 0 )).getAttribute( "type" );

                ca.addProperty( "set", name, setMethod, paramType, attributed, true, null );
              }
            }
          }
          // Make sure there aren't duplicates of this property.
          propertiesRegister.remove( componentName );
          propertiesRegister.put( componentName, ca );
        }
        catch ( Exception ex ) {
          ex.printStackTrace();
        }
      }
    }
    catch ( Exception ex ) {
      if ( BuildProperties.DEBUG )
        DebugLogger.logError( "Unable to setup the component registry" );
    }
  }

  /**
   * Create a new component adapter
   * @param owner the name ofthe owning module
   * @param componentName the component name
   * @param iconName the icon file
   * @param clazz the class file name
   * @param ui the name of the ui
   * @throws java.lang.ClassNotFoundException problems finding the class
   * @return the new component adapter
   */
  public ComponentAdapter addComponentAdapter( String owner, String componentName, String iconName, String clazz, String ui ) throws ClassNotFoundException
  {
    return new ComponentAdapter( clazz, ui );
  }

  /**
   * Create a new reflection component adapter, that is an adapter that uses
   * reflection to find a suitable getter or setter.
   * @param owner the name ofthe owning module
   * @param componentName the component name
   * @param iconName the icon file
   * @param clazz the class file name
   * @param ui the name of the ui
   * @throws java.lang.ClassNotFoundException problems finding the class
   * @return the new component adapter
   */
  public ComponentAdapter addReflectionAdapter( String owner, String componentName, String iconName, String clazz, String ui ) throws ClassNotFoundException
  {
    return new ReflectionAdapter( clazz, ui );
  }

  /**
   * Check that all the registered components are loaded
   */
  public void checkRegistration()
  {
    if ( localChangeCounter != changeCounter ) {
      read();
      localChangeCounter = changeCounter;
    }
  }
}
TOP

Related Classes of net.xoetrope.registry.XRegisteredComponentFactory

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.