Package jfun.yan.xml.nut

Source Code of jfun.yan.xml.nut.Nut

package jfun.yan.xml.nut;


import java.net.MalformedURLException;

import jfun.yan.Component;
import jfun.yan.ParameterBinder;
import jfun.yan.PropertyBinder;
import jfun.yan.xml.ConfigurationException;
import jfun.yan.xml.Location;
import jfun.yan.xml.NutEnvironment;
import jfun.yan.xml.NutsUtils;

/**
* The super class of all Nut classes.
* <p>
* Nut stands for Name based User defineable Tag.
* A method whose name and signature is of a certain pre-defined pattern is
* called when a sub-element with corresponding name is interpreted
* inside the xml tag.
* </p>
* <p>
* For example, for the following tag:<br>
* <pre>
* &lt;ctor class="A"&gt;
*   &lt;arg ind="0" val="1"&gt;
* &lt;/ctor&gt;
* </pre>
* </p>
* <p>
* Method <code>setClass</code> is called for the "class" attribute,
* which is of course same as the standard Java Bean convention.
* In fact, a Nut class is always a Java Bean because it has to
* have a default public constructor and some setters to
* set attributes.
* </p>
* <p>
* Method <code>addArg</code> is called for each sub-element.
* And the parameter type of addArg should be another Nut class
* to support further "tagging".
* </p>
* <p>
* For tags simply with a list of sub-elements whose names are
* irrelevant, the <code>set</code> method with an array parameter is called.
* <br>
* For example:
* <pre>
* &lt;array&gt;
*   &lt;return val="1"&gt;
*   &lt;ctor class="B"&gt;
*   &lt;method class="C" name="f"&gt;
* &lt;/array&gt;
* </pre>
* </p>
* <p>
* Finally, a Nut class can optionally have a method named <code>"eval"</code>.
* If this method exist, it is invoked when the tag is evaluated.
* If the return type is void or the "eval" method does not exist,
* the Nut object itself is used as the evaluation result.
* Otherwise, the return value of the "eval" method is used.
* </p>
* @author Ben Yu
* Nov 9, 2005 10:08:11 PM
*/
public abstract class Nut implements java.io.Serializable{
  private Location loc;
  private NutEnvironment env;
  private String tagname;
  private String id;
  private boolean globallyDefined;
  private int seq_no;
  /**
   * Is this tag defined globally?
   */
  public boolean isGloballyDefined(){
    return globallyDefined;
  }
  /**
   * Dynamically register an object.
   * @param key the key of the object.
   * @param val the object.
   * @param overridable whether this registration is overridable.
   * @param overriding do we override when the same key is already used
   * by another dynamically registered entry.
   */
  public void register(Object key, Object val,
      boolean overridable, boolean overriding){
    env.registerDynamic(key, val, overridable, overriding, loc);
  }
  /**
   * Get the sequence number starting from 0.
   * This number is relative to the order the tag is defined within the current scope.
   */
  public int getSequenceNumber(){
    return seq_no;
  }
  /**
   * Get the id of this tag.
   * @return the id.
   */
  public String getId() {
    return id;
  }
  /**
   * Set the id of the tag.
   * @param id the id.
   */
  public void setId(String id) {
    this.id = id;
  }
  public String toString() {
    return tagname;
  }
  /**
   * Get this tag's location within the configuration file.
   */
  public Location getTagLocation(){
    return loc;
  }
  /**
   * To set the sequence number of the tag in the enclosing scope.
   * @param seq the sequence number.
   */
  public void initSequenceNumber(int seq){
    this.seq_no = seq;
  }
  /**
   * To set whether the tag is defined globally.
   * @param gd the flag.
   */
  public void initGloballyDefined(boolean gd){
    this.globallyDefined = gd;
  }
  /**
   * The framework calls this method to set the location.
   * @param loc the location.
   */
  public void initTagLocation(Location loc){
    this.loc = loc;
  }
  /**
   * The framework calls this method to set the environment.
   * @param env the environment.
   */
  public void initNutEnvironment(NutEnvironment env){
    this.env = env;
  }
  /**
   * Get the class loader used to load the component classes.
   */
  public ClassLoader getComponentClassLoader() {
    return env.getComponentClassLoader();
  }
  /**
   * Get a ClassLoader object that uses the current ClassLoader
   * as parent, and tries an alternative classpath if the resource
   * or class is not found.
   *
   * @param classpath the alternative classpath. null if unspecified.
   * @return the ClassLoader object.
   */
  public ClassLoader getNutClassLoader(String classpath){
    try{
      return NutsUtils.getClassLoader(getClass().getClassLoader(),
          classpath,
          env.getBaseDir());
    }
    catch(MalformedURLException e){
      throw new ConfigurationException("invalid classpath",
          loc);
    }
  }
  /**
   * The framework calls this method to set the tag name.
   * @param name the tag name.
   */
  public void initTagName(String name){
    this.tagname = name;
  }
  /**
   * Get the environment that the Nut object is running in.
   */
  public NutEnvironment getNutEnvironment() {
    return env;
  }

  /**
   * Convert an object to a target type.
   * @param target_type the target type.
   * @param v the object to be converted.
   * @return the object of the target type.
   */
  public Object convert(Class target_type, Object v){
    return env.convert(target_type, v, loc);
  }
  /**
   * Transforms a Component so that the instantiated instance
   * is converted to the target type.
   * @param target_type the target type.
   * @param c the component.
   * @return the new Component with the conversion in effect.
   */
  public Component cast(final Class target_type, Component c){
    return env.cast(target_type, c, this.getTagLocation());
  }
  /**
   * Get the tag name.
   */
  public String getTagName() {
    return tagname;
  }
 
  /**
   * Register a Component to be eagerly instantiated using the current tag's id.
   * @param c the Component to be eagerly instantiated.
   */
  public void registerEagerInstantiation(Component c){
    if(!globallyDefined){
      raise("only global tags can be registered as eager instantiated");
    }
    /*
    if(id==null){
      raise("id is required to eager initialize a Component");
    }*/
    env.registerEagerInstantiation(seq_no, id, c);
  }
  /**
   * Throws a ConfigurationException with the current tag name and location information.
   * @param msg the error message.
   * @return This method never returns. The return type is for
   * callers to get around of the type system so that you can say
   * "throw raise(...)".
   */
  public ConfigurationException raise(String msg){
    throw new ConfigurationException(tagname+": " + msg, loc);
  }
  /**
   * Throws a ConfigurationException with the current tag name and location information.
   * @param e the nested exception.
   * @return This method never returns. The return type is for
   * callers to get around of the type system so that you can say
   * "throw raise(...)".
   */
  public ConfigurationException raise(Throwable e){
    throw new ConfigurationException(tagname+": " + e.getMessage(), e, loc);
  }
 
  /**
   * Make sure an object is not null.
   * Proper error message is reported otherwise.
   * @param attrname the name of the checked attribute.
   * @param v the attribute value.
   */
  protected void checkMandatory(String attrname, Object v){
    if(v==null)
      raise("missing mandatory attribute <"+attrname +">");
  }
  /**
   * Make sure at least one of two attributes is present.
   * @param name1 the name of the first attribute.
   * @param v1 the value of the first attribute.
   * @param name2 the name of the second attribute.
   * @param v2 the value of the second attribute.
   */
  protected void checkMandatory(String name1, Object v1,
      String name2, Object v2){
    if(v1==null&&v2==null)
      raise("either <"+name1+"> or <"+ name2+ "> has to be specified.");
  }
  /**
   * Makes sure that a certain attribute is not set yet
   * to avoid duplicate setting.
   * @param attrname the attribute name.
   * @param v the attribute value.
   */
  protected void checkDuplicate(String attrname, Object v){
    if(v!=null){
      raise("attribute <"+attrname+"> already specified.");
    }
  }
  /**
   * Makes sure the array only contains one element.
   * This is useful for tags accepting only one sub-element.
   * @param vals the value array.
   */
  /*protected void checkSingleChild(Object[] vals){
    if(vals.length>1)
      throw raise("only one sub-element is allowed");
  }*/
 
  /**
   * To get the ParameterBinder object that encapsulates the auto-wiring strategy
   * for a autowire mode specified by the mode name.
   *
   * @param mode the mode name.
   * @return the ParameterBinder object for the auto-wiring strategy.
   * null is returned if this indicates a manual-wire.
   */
  public ParameterBinder getParameterWiring(String mode){
    return env.getParameterWiringMode(mode, loc);
  }
  /**
   * To get the PropertyBinder object that encapsulates the auto-wiring strategy
   * for a autowire mode specified by the mode name.
   *
   * @param mode the mode name.
   * @return the PropertyBinder object for the auto-wiring strategy.
   * null is returned if this indicates a manual-wire.
   */
  public PropertyBinder getPropertyWiring(String mode){
    return env.getPropertyWiringMode(mode, loc);
  }
 
  //should have a method eval(). return type can be anything.
}
TOP

Related Classes of jfun.yan.xml.nut.Nut

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.