Open Source Repository

Home /hibernate/hibernate-3.2.6.ga | Repository Home


org/hibernate/dialect/function/SQLFunctionTemplate.java
//$Id: SQLFunctionTemplate.java 6608 2005-04-29 15:32:30Z oneovthafew $
package org.hibernate.dialect.function;

import org.hibernate.QueryException;
import org.hibernate.engine.Mapping;
import org.hibernate.engine.SessionFactoryImplementor;
import org.hibernate.type.Type;

import java.util.ArrayList;
import java.util.List;

/**
 * Represents HQL functions that can have different representations in different SQL dialects.
 * E.g. in HQL we can define function <code>concat(?1, ?2)</code> to concatenate two strings 
 * p1 and p2. Target SQL function will be dialect-specific, e.g. <code>(?1 || ?2)</code> for 
 * Oracle, <code>concat(?1, ?2)</code> for MySql, <code>(?1 + ?2)</code> for MS SQL.
 * Each dialect will define a template as a string (exactly like above) marking function 
 * parameters with '?' followed by parameter's index (first index is 1).
 *
 @author <a href="mailto:[email protected]">Alexey Loubyansky</a>
 @version <tt>$Revision: 6608 $</tt>
 */
public class SQLFunctionTemplate implements SQLFunction {
  private final Type type;
  private final boolean hasArguments;
  private final boolean hasParenthesesIfNoArgs;

  private final String template;
  private final String[] chunks;
  private final int[] paramIndexes;

  public SQLFunctionTemplate(Type type, String template) {
    thistype, template, true );
  }

  public SQLFunctionTemplate(Type type, String template, boolean hasParenthesesIfNoArgs) {
    this.type = type;
    this.template = template;

    List chunkList = new ArrayList();
    List paramList = new ArrayList();
    StringBuffer chunk = new StringBuffer10 );
    StringBuffer index = new StringBuffer);

    for int i = 0; i < template.length(); ++i ) {
      char c = template.charAt);
      if c == '?' ) {
        chunkList.addchunk.toString() );
        chunk.delete0, chunk.length() );

        while ++i < template.length() ) {
          c = template.charAt);
          if Character.isDigit) ) {
            index.append);
          }
          else {
            chunk.append);
            break;
          }
        }

        paramList.addnew IntegerInteger.parseIntindex.toString() ) ) );
        index.delete0, index.length() );
      }
      else {
        chunk.append);
      }
    }

    if chunk.length() ) {
      chunkList.addchunk.toString() );
    }

    chunks = String[] ) chunkList.toArraynew String[chunkList.size()] );
    paramIndexes = new int[paramList.size()];
    for int i = 0; i < paramIndexes.length; ++i ) {
      paramIndexes[i( ( Integer paramList.get) ).intValue();
    }

    hasArguments = paramIndexes.length > 0;
    this.hasParenthesesIfNoArgs = hasParenthesesIfNoArgs;
  }

  /**
   * Applies the template to passed in arguments.
   @param args function arguments
   *
   @return generated SQL function call
   */
  public String render(List args, SessionFactoryImplementor factory) {
    StringBuffer buf = new StringBuffer();
    for int i = 0; i < chunks.length; ++i ) {
      if i < paramIndexes.length ) {
        Object arg = paramIndexes[i< args.size() ? args.getparamIndexes[i] ) null;
        if arg != null ) {
          buf.appendchunks[i] ).appendarg );
        }
      }
      else {
        buf.appendchunks[i] );
      }
    }
    return buf.toString();
  }

  // SQLFunction implementation

  public Type getReturnType(Type columnType, Mapping mappingthrows QueryException {
    return type;
  }

  public boolean hasArguments() {
    return hasArguments;
  }

  public boolean hasParenthesesIfNoArguments() {
    return hasParenthesesIfNoArgs;
  }
  
  public String toString() {
    return template;
  }
}