Location: PHPKode > projects > Sierra-php PHP Application Framework > sierra/lib/model/dao.tpl
<?php
{if $headerTemplate}{$Template->display($headerTemplate)}


{/if}
// {ldelim}{ldelim}{ldelim} Header
/*
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 | SIERRA : PHP Application Framework  http://code.google.com/p/sierra-php |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 |                   *** DO NOT EDIT THIS FILE ***                         |
 |                                                                         |
 | This dtd source file was generated by the SIERRA Entity modeler.        |
 | according to the entity model described in the source file listed below.|
 | This file will be overwritten each time a change to that file is made.  |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 entity model source file: {$entityModelPath}
 */
// {rdelim}{rdelim}{rdelim}
{$Template->assign("aopClassType", $smarty.const.SRA_AOP_CLASS_DAO)}
// {ldelim}{ldelim}{ldelim} Imports
require_once('model/SRA_WS.php');
{if $entity->_daoExtendsFile}
require_once({$entity->getIncludePath($entity->_daoExtendsFile)});
{/if}

{foreach from=$includes item=include}
require_once('{$include}');
{/foreach}
// {rdelim}{rdelim}{rdelim}

// {ldelim}{ldelim}{ldelim} Constants
  // aop constants
{foreach from=$entity->getAopIntroductions($smarty.const.SRA_AOP_INTRODUCTION_TYPE_CONSTANT, $aopClassType) item=introduction}
  define('{$introduction->getValue(0)}', {$introduction->getValue(1)});
{/foreach}
// {rdelim}{rdelim}{rdelim}

// {ldelim}{ldelim}{ldelim} {$className}
/**
 * This Data Access Object (DAO) was generated from the definition specified in 
 * {$entity->_entityModelXml}
 * It will be overwritten every time a change to that file is made
 * 
 * {if $entity->_apiResource}{$resources->getString($entity->_apiResource)}{else}{$resources->getString($entity->_resource)}{/if}

 * 
 */
class {$className}{if $entity->_daoExtends} extends {$entity->_daoExtends}{/if} {ldelim}
  // {ldelim}{ldelim}{ldelim} Attributes
  // public attributes
  /**
   * temporarily stores the # of results returned by the last invocation of any 
   * of the find methods
   */
  var $resultCount;
  
  /**
   * temporarily stores the total # of results for the last invocation of any of 
   * the find methods. this is the # of records that would have been returned 
   * had limit and offsets not been applied (if applicable)
   */
  var $totalResultCount;
  
  // private attributes
  /**
   * SRA_Database instance used by this DAO
   * @type SRA_Database
   * @access private
   */
  var $_db;
  
  // aop attributes
{foreach from=$entity->getAopIntroductions($smarty.const.SRA_AOP_INTRODUCTION_TYPE_ATTRIBUTE, $aopClassType) item=introduction}
  var ${$introduction->getValue()};
{/foreach}
  
  // {rdelim}{rdelim}{rdelim}
  
  // {ldelim}{ldelim}{ldelim} Operations
  
  // constructor
  // {ldelim}{ldelim}{ldelim} {$className}
  /**
   * {$className} constructor. this class should only be instantiated by the 
   * SRA_DaoFactory
   * @access  package
   */
  function {$className}() {ldelim} 
    {$Template->assign('aopMethodName', $className)}
    {include file="entity-aspect-before.tpl"}
    if (!SRA_Database::isValid($this->_db =& SRA_Controller::getAppDb({if $entity->_db}'{$entity->_db}'{/if}))) {ldelim}
      $msg = "{$className}::{$className}: Failed to obtain reference to a SRA_Database object instance";
      SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    {include file="entity-aspect-after.tpl"}
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // public methods
  
  
  // {ldelim}{ldelim}{ldelim} convertAttribute
  /**
   * prepares $value for use in a db query based on the datatype of $attribute. 
   * this method can only be called for scalar attributes
   * @param mixed $value the value to convert
   * @param string $attribute the name of the attribute to return the column 
   * name for. if not specified, it will be assumed that $value is a primary 
   * key value
   * @access  public
   * @return string
   */
  function convertAttribute($value, $attribute = NULL) {ldelim}
    {$Template->assign('aopMethodName', "convertAttribute")}
    {include file="entity-aspect-before.tpl"}
    // base entity table
    if (!$attribute) {ldelim} $attribute = '{$primaryKey->_name}'; {rdelim}
    // attribute specific table
    $db =& SRA_Controller::getAppDb();
{foreach from=$entity->getAttributes() item=attribute}
{if !$attribute->isEntity()}
    if ($attribute == '{$attribute->_name}') {ldelim}
      $value = $db->{$attribute->getConvertMethodName()}($value);
    {rdelim}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
    return $value;
  {rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} convertPk
  /**
   * This method prepares a primary key value for a database query
   * 
   * @param {$primaryKey->_type} $id the primary key value to convert
   * @access  public
   * @return string
   */
  function convertPk($id) {ldelim}
    {$Template->assign('aopMethodName', "convertPk")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    return $this->_db->{$primaryKey->getConvertMethodName()}($id);
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} delete
  /**
   * This method is used to delete an existing {$entity->_name} object
   * @param {$voClassName} $record The {$entity->_name} instance to delete
   
   * @access  public
   * @return void
   */
  function delete(& $record) {ldelim}
    {$Template->assign('aopMethodName', "delete")}
    {include file="entity-aspect-before.tpl"}
    static $deletingRecord = array();
    
    // check if param is a valid {$voClassName} instance
    if (!{$voClassName}::isValid($record)) {ldelim}
      $msg = "{$className}::delete: Failed - parameter is not a valid {$voClassName} instance";
      {include file="entity-aspect-after.tpl"}
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    
    // validate deletion for {$voClassName}
    if (!$record->validateDelete()) {ldelim}
      {include file="entity-aspect-after.tpl"}
      $msg = "{$className}::delete: Failed - {$voClassName} deletion validation failed: " . implode(', ', $record->validateErrors);
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    
    // validate primary key
    if (!$record->getPrimaryKey()) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return FALSE;
    {rdelim}

    // does record already exist
    if (!$record->recordExists) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return FALSE; 
    {rdelim}
    
    // avoid recursive looping
    if ($deletingRecord[$record->getPrimaryKey()]) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return FALSE;
    {rdelim}
    
    $deleteRecordId = $record->getPrimaryKey();
    $deletingRecord[$deleteRecordId] = TRUE;
    
    // all ok, continue with update
    
    // start transaction
    $completeTransaction = TRUE;
    if (!$this->_db->isInTransaction()) {ldelim}
      $this->_db->startTransaction();
    {rdelim}
    else {ldelim}
      $completeTransaction = FALSE;
    {rdelim}
    
{* cascade deletes if necessary *}
{if !$schema->isDbRefIntegrity()}
    $deleteQueries = array();
{foreach from=$schema->getTables() item=table}{$schema->setProcessed($table->getName(), 0)}{/foreach}
{foreach from=$schema->getTables() item=table}
{foreach from=$table->getAttributeGroups() item=attrs}
{foreach from=$attrs key=attrId item=attr}
{assign var=attribute value=$entity->getAttributes($attr)}
{if $attribute->_tablePkColumn}{assign var=pkColName value=$attribute->_tablePkColumn}{else}{assign var=pkColName value=$primaryKey->_column}{/if}
{assign var=foreignEntity value="0"}
{if $attribute->isEntity()}{assign var=foreignEntity value=$entity->getEntityGenerator($attribute->_type)}{/if}
{assign var=column value=$table->getAttributeColumn($attrId)}
{* cascade delete entity *}
{if $attribute->isEntity() && $attribute->_onDeleteCascade}

    $attr ={if $attribute->_useReference}&{/if} $record->getAttribute('{$attr}');
    $dao =& SRA_DaoFactory::getDao('{$attribute->_type}');
{if $attribute->_cardinality}
    if (!$attr) {ldelim}
      $attr = array();
    {rdelim}
    $keys = array_keys($attr);
    foreach ($keys as $key) {ldelim}
{/if}
      if ($attr{if $attribute->_cardinality}[$key]{/if} && SRA_Error::isError($dao->delete($attr{if $attribute->_cardinality}[$key]{/if}))) {ldelim}
        $msg = '{$className}::delete: Failed - Unable to cascade delete to {$attribute->_name} attribute';
        {include file="entity-aspect-after.tpl"}
        return SRA_Error::logError($msg, __FILE__, __LINE__);    
      {rdelim}
{if $table->getName() neq $foreignEntity->_table && $table->getName() neq $entity->_table}
      $deleteQueries[] = 'DELETE FROM {$table->getName()} WHERE {$pkColName} = ' . $record->getAttrDbValue();
{/if}
{if $attribute->_cardinality}
    {rdelim}
{/if}

{* otherwises delete or update table *}
{elseif $attr neq $primaryKey->_name && $table->getName() neq $entity->_table}
{assign var=processQuery value="0"}
{if !$schema->isProcessed($table->getName()) && ((!$attribute->isEntity() && (!$attribute->_onDeleteCascadeSet || ($attribute->_onDeleteCascadeSet && $attribute->_onDeleteCascade))) || ($attribute->isEntity() && $table->getName() neq $foreignEntity->_table))}
{assign var=processQuery value="1"}

    $deleteQueries[] = 'DELETE FROM {$table->getName()} WHERE {$pkColName} = ' . $record->getAttrDbValue();
{elseif !$schema->isProcessed($table->getName()) && (($attribute->isEntity() && $table->getName() eq $foreignEntity->_table) || ($attribute->_onDeleteCascadeSet && !$attribute->_onDeleteCascade))}
{assign var=processQuery value="1"}

    $deleteQueries[] = 'UPDATE {$table->getName()} SET {$pkColName} = {if $attribute->_nullDbEmptyStr}\'\'{else}NULL{/if} WHERE {$pkColName} = ' . $record->getAttrDbValue();
{/if}
{if !$schema->isProcessed($table->getName()) && $processQuery}{$schema->setProcessed($table->getName())}{/if}
{/if}      {* $attribute->isEntity() && $attribute->_onDeleteCascade *}
{/foreach} {* $table->getAttributeGroups() *}
{/foreach} {* $attrs *}
{/foreach} {* $schema->getTables() *}

    foreach ($deleteQueries as $sql) {ldelim}
      if (SRA_Error::isError($results =& $this->_db->execute($sql))) {ldelim}
        if ($completeTransaction) {ldelim} $this->_db->rollback(); {rdelim}
        $msg = "{$className}::delete: Failed - SRA_Database query '${ldelim}sql{rdelim}' resulted in an SRA_Error";
        {include file="entity-aspect-after.tpl"}
        return SRA_Error::logError($msg, __FILE__, __LINE__);
      {rdelim}
    {rdelim}

{* delete cascaded entities not handled by db *}
{else}
{foreach from=$schema->getTables() item=table}
{if $table->getName() neq $primaryTable->getName()}
{foreach from=$table->getAttributeGroups() item=attrs}
{foreach from=$attrs key=attrId item=attr}
{assign var=attribute value=$entity->getAttributes($attr)}
{if $attribute->isEntity() && $attribute->_onDeleteCascade}
{assign var=foreignEntity value=$entity->getEntityGenerator($attribute->_type)}
{if $table->getName() neq $foreignEntity->_table}

    $attr ={if $attribute->_useReference}&{/if} $record->getAttribute('{$attr}');
    $dao =& SRA_DaoFactory::getDao('{$attribute->_type}');
{if $attribute->_cardinality}
    if (!$attr) {ldelim}
      $attr = array();
    {rdelim}
    $keys = array_keys($attr);
    foreach ($keys as $key) {ldelim}
{/if}
    if ($attr{if $attribute->_cardinality}[$key]{/if} && SRA_Error::isError($dao->delete($attr{if $attribute->_cardinality}[$key]{/if}))) {ldelim}
      $msg = '{$className}::delete: Failed - Unable to cascade delete to {$attribute->_name} attribute';
      {include file="entity-aspect-after.tpl"}
      return SRA_Error::logError($msg, __FILE__, __LINE__);    
    {rdelim}
{if $attribute->_cardinality}
    {rdelim}
{/if}
{/if}      {* $table->getName() neq $foreignEntity->_table *}
{/if}      {* $attribute->isEntity() && $attribute->_onDeleteCascade *}
{/foreach} {* $attrs *}
{/foreach} {* $table->getAttributeGroups() *}
{/if}      {* $table->getName() neq $primaryTable->getName() *}
{/foreach} {* $schema->getTables() *}
{/if}      {* !$schema->isDbRefIntegrity() *}
    
{if $primaryTable->getDeleteConstraint()}
    $sql = "UPDATE {$primaryTable->getName()} SET {$primaryTable->getDeleteConstraint()} WHERE {$primaryTable->getPrimaryKey()} = " . $record->getAttrDbValue();
{else}
    $sql = "DELETE FROM {$primaryTable->getName()} WHERE {$primaryTable->getPrimaryKey()} = " . $record->getAttrDbValue();
{/if}
    if (SRA_Error::isError($results =& $this->_db->execute($sql))) {ldelim}
      if ($completeTransaction) {ldelim} $this->_db->rollback(); {rdelim}
      $msg = "{$className}::delete: Failed - SRA_Database query '${ldelim}sql{rdelim}' resulted in an SRA_Error";
      {include file="entity-aspect-after.tpl"}
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    $record->recordExists = FALSE;

    // commit transaction updates
    if ($completeTransaction) {ldelim} $this->_db->commit(); {rdelim}
    
    $deletingRecord[$deleteRecordId] = FALSE;
    
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_isFile}
    $attr =& $record->getAttribute('{$attribute->_name}');
{if $attribute->_cardinality}
    $keys = array_keys($attr);
    foreach ($keys as $key) {ldelim}
{/if}
    if (SRA_FileAttribute::isValid($attr{if $attribute->_cardinality}[$key]{/if})) {ldelim}
      $attr{if $attribute->_cardinality}[$key]{/if}->delete();
    {rdelim}
{if $attribute->_cardinality}
    {rdelim}
{/if}
{/if}
{/foreach}
    
    $deleted = TRUE;
    {include file="entity-aspect-after.tpl"}
    
    return $deleted;
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} findAll
  /**
   * Used to return all of the {$entity->_name} in the database table
   * @param int $limit the max # of records to return
   * @param int $offset the first record (where 0 is the first row) to begin 
   * considering
   * @access  public
   * @return {$voClassName}[]
   */
  function &findAll($limit=NULL, $offset=NULL) {ldelim}
    {$Template->assign('aopMethodName', "findAll")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    return $this->_find(FALSE, $limit, $offset);
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} findByConstraints
  /**
   * Used to return all of the {$entity->_name} records that have matching attr 
   * values. all attributes must be scalar and stored in the primary entity 
   * table
   * @param array $constraints attr/value pairs to match
   * @param array $sqlConstraint an optional sql constraint to apply. should 
   *               be specified in the format "col1=val1[ AND col2=val2]" 
   *              (will not be validated for sql accuracy)
   * @param array $sqlOrderConstraint an optional sql ordering constraint. should 
   *              be specified in the format "col1 [ASC|DESC], [col2 [ASC|DESC]]"
   *              (will not be validated for sql accuracy)
   * @param int $limit the max # of records to return
   * @param int $offset the first record (where 0 is the first row) to begin 
   * considering
   * @access  public
   * @return {$voClassName}[]
   */
  function &findByConstraints($constraints, $sqlConstraint=FALSE, $sqlOrderConstraint=FALSE, $limit=NULL, $offset=NULL) {ldelim}
    {$Template->assign('aopMethodName', "findByConstraints")}
    {include file="entity-aspect-before.tpl"}
    
    // check if param is a valid {$voClassName} instance
    if (!is_array($constraints)) {ldelim}
      $msg = "{$className}::findByConstraints: Failed - constraints must be an array with 1 or more column/value pairs";
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    
    // convert to sql constraints
    $sqlConstraints = array();
    foreach($constraints as $attr => $val) {ldelim}
      $sqlConstraints[$this->getColumnName($attr)] = $this->convertAttribute($val, $attr);
    {rdelim}
    
    {include file="entity-aspect-after.tpl"}
    return $this->findBySqlConstraints($sqlConstraints, $sqlConstraint, $sqlOrderConstraint, $limit, $offset);
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} findByPk
  /**
   * This method is used to lookup an existing {$entity->_name} object based on 
   * a primary key value
   * @param {$primaryKey->_type} $id the primary key of the {$entity->_name} object to return
   * @param boolean $reload whether or not to ignore any cached versions of the object
   * @access  public
   * @return {$voClassName}
   */
  function &findByPk($id, $reload=FALSE) {ldelim}
    {$Template->assign('aopMethodName', "findByPk")}
    {include file="entity-aspect-before.tpl"}
    // check if id is valid
    if (!$id || !is_scalar($id)) {ldelim}
      $msg = "{$className}::findByPk: Failed - No id specified or is not scalar: Type - " . gettype($id) . " Value - " . $id;
      {include file="entity-aspect-after.tpl"}
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    {include file="entity-aspect-after.tpl"}
    return $this->_find($id, FALSE, FALSE, FALSE, FALSE, FALSE, $reload);
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} findByPks
  /**
   * Returns all of the {$entity->_name} records with ids matching those 
   * specified in the ids parameter
   * 
   * @param int[] $ids the primary key values of the {$entity->_name} records to 
   * return. if this parameter is a SRA_ResultSet object, then the ids will be 
   * extracted from the 1st element of each row in those results.
   * @param int $limit INTERNAL USE ONLY, DO NOT USE
   * @param int $offset INTERNAL USE ONLY, DO NOT USE
   * @param string $altModel an alternate VO to initialize. this class MUST be 
   * a subclass of {$voClassName}
   * @param array $altModelInitVals an array of associative arrays of init values that 
   * apply to the $altModel class specified. these will be added to the base 
   * init values for the {$voClassName}. Each element in this array must correspond 
   * with an $ids index
   * @access  public
   * @return {$voClassName}[]
   */
  function &findByPks($ids, $limit=NULL, $offset=NULL, $altModel=FALSE, $altModelInitVals=FALSE) {ldelim}
    {$Template->assign('aopMethodName', "findByPks")}
    {include file="entity-aspect-before.tpl"}
    // validate altModelInitVals
    if (is_array($altModelInitVals) && count($altModelInitVals) != count($ids)) {ldelim}
      $msg = "{$className}::findByPks: Failed - # of ids not equal to # of altModelInitVals";
      {include file="entity-aspect-after.tpl"}
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    
    // convert SRA_ResultSet
    if (SRA_ResultSet::isValid($ids)) {ldelim}
      $tmp = array();
      while($row =& $ids->next()) {ldelim}
        $tmp[] = $row[0];
      {rdelim}
      $ids = $tmp;
    {rdelim}
    {include file="entity-aspect-after.tpl"}
    return $this->_find($ids, $limit, $offset, FALSE, $altModel, $altModelInitVals);
    
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} findByQuery
  /**
   * Used to return all of the {$entity->_name} whose primary key is returned in 
   * a sql query
   * @param string $query the query to perform. the first result value in this 
   * query should be the primary key values of the {$entity->_name}s to return
   * @param int $limit the max # of records to return
   * @param int $offset the first record (where 0 is the first row) to begin 
   * considering
   * @param boolean $leftJoin whether or not left joins should be used to join  
   * the tables specified in this query to the primary entity table. the default 
   * to join using the WHERE clause which will requires that a 1..1 or 1..* 
   * relationship exists between the joined table and the primary entity table
   * @access  public
   * @return {$voClassName}[]
   */
  function &findByQuery($query, $limit=NULL, $offset=NULL, $leftJoin=FALSE) {ldelim}
    {$Template->assign('aopMethodName', "findByQuery")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    return $this->_find($query, $limit, $offset, $leftJoin);
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} findBySqlConstraints
  /**
   * Used to return all of the {$entity->_name} records that have matching sql 
   * values. all columns must be scalar and exist in the primary entity table
   * @param array $constraints column/value pairs to match. the value must be db prepared
   * @param array $sqlConstraint an optional sql constraint to apply. should 
   *               be specified in the format "col1=val1[ AND col2=val2]" 
   *              (will not be validated for sql accuracy)
   * @param array $sqlOrderConstraint an optional sql ordering constraint. should 
   *              be specified in the format "col1 [ASC|DESC], [col2 [ASC|DESC]]"
   *              (will not be validated for sql accuracy)
   * @param int $limit the max # of records to return
   * @param int $offset the first record (where 0 is the first row) to begin 
   * considering
   * @access  public
   * @return {$voClassName}[]
   */
  function &findBySqlConstraints($constraints, $sqlConstraint=FALSE, $sqlOrderConstraint=FALSE, $limit=NULL, $offset=NULL) {ldelim}
    {$Template->assign('aopMethodName', "findBySqlConstraints")}
    {include file="entity-aspect-before.tpl"}
    
    // check if param is a valid {$voClassName} instance
    if (!is_array($constraints)) {ldelim}
      $msg = "{$className}::findBySqlConstraints: Failed - constraints must be an array with 1 or more column/value pairs";
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    
    $sql = "SELECT {$primaryKey->_column} FROM {$entity->_table} WHERE 1=1"{if $entity->_constraint} . " AND {$entity->_constraint}"{/if};
    foreach ($constraints as $col => $val) {ldelim}
      $sql .= " AND $col=$val";
    {rdelim}
    if ($sqlConstraint) {ldelim}
      $sql .= ' AND (' . $sqlConstraint . ')';
    {rdelim}
    if ($sqlOrderConstraint) {ldelim}
      $sql .= ' ORDER BY ' . $sqlOrderConstraint;
    {rdelim}
{if $entity->_orderBy}
    if (!$sqlOrderConstraint) {ldelim}
      $sql .= " ORDER BY {$entity->_orderBy}";
    {rdelim}
{/if}
    {include file="entity-aspect-after.tpl"}
    return $this->_find($sql, $limit, $offset);
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} findEqual
  /**
   * Used to return all of the {$entity->_name} records that have the same 
   * attribute values as the $record specified
   * @param {$voClassName} $record the {$voClassName} object to match. only 
   * attributes that are set (and not the primary key) will be compared. 
   * relational attributes will not be considered.
   * @param int $limit the max # of records to return
   * @param int $offset the first record (where 0 is the first row) to begin 
   * considering
   * @access  public
   * @return {$voClassName}[]
   */
  function &findEqual(& $record, $limit=NULL, $offset=NULL) {ldelim}
    {$Template->assign('aopMethodName', "findEqual")}
    {include file="entity-aspect-before.tpl"}
    // check if param is a valid {$voClassName} instance
    if (!{$voClassName}::isValid($record)) {ldelim}
      $msg = "{$className}::findEqual: Failed - parameter is not a valid {$voClassName} instance";
      {include file="entity-aspect-after.tpl"}
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    
    $sql = "SELECT {$primaryKey->_column} FROM {$entity->_table} WHERE 1=1"{if $entity->_constraint} . " AND {$entity->_constraint}"{/if};
{foreach from=$entity->getAttributes() item=attribute}
{if !$attribute->_table && !$attribute->_setOnly && !$attribute->isEntity() && !$attribute->_isFile && !$attribute->getMappedAttributes() && !$attribute->_skipPersistence}
    if ($record->get{$attribute->getMethodName()}()) {ldelim}
{if $attribute->_mappedTo}
      $attr = {if $attribute->_useReference}&{/if}$record->getAttribute('{$attribute->_mappedTo}');
      $attr = $attr->get{$attribute->_columnMapping->getMethodName()}();
{/if}
      $sql .= ' AND {$attribute->_column} = {if $attribute->_setFunction}{$attribute->_setFunction}({/if}' . $record->getAttrDbValue('{$attribute->_name}', {if $attribute->_mappedTo}$attr{else}$record->get{$attribute->getMethodName()}(){/if}){if $attribute->_setFunction} . ')'{/if};
    {rdelim}
{/if}
{/foreach}
    {if $entity->_orderBy}$sql .= " ORDER BY {$entity->_orderBy}";{/if}
    {include file="entity-aspect-after.tpl"}
    return $this->_find($sql, $limit, $offset);
    
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} findLike
  /**
   * Used to return all of the {$entity->_name} records that have like 
   * attribute values as the $record specified
   * @param {$voClassName} $record the {$voClassName} object to match. only 
   * attributes that are set (and not the primary key) will be compared. 
   * relational attributes will not be considered. otherwise just 
   * case-insensitive matches will be considered
   * @param boolean $matchSubstrings whether or not substrings should be matched
   * default value for this parameter is TRUE
   * @param int $limit the max # of records to return
   * @param int $offset the first record (where 0 is the first row) to begin 
   * considering
   * @access  public
   * @return {$voClassName}[]
   */
  function &findLike(& $record, $matchSubstrings=TRUE, $limit=NULL, $offset=NULL) {ldelim}
    {$Template->assign('aopMethodName', "findLike")}
    {include file="entity-aspect-before.tpl"}
    // check if param is a valid {$voClassName} instance
    if (!{$voClassName}::isValid($record)) {ldelim}
      $msg = "{$className}::findLike: Failed - parameter is not a valid {$voClassName} instance";
      {include file="entity-aspect-after.tpl"}
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    
    $sstr = '';
    if ($matchSubstrings) {ldelim}
      $sstr = '%';
    {rdelim}
    
    $sql = "SELECT {$primaryKey->_column} FROM {$entity->_table} WHERE 1=1"{if $entity->_constraint} . " AND {$entity->_constraint}"{/if};
{foreach from=$entity->getAttributes() item=attribute}
{if !$attribute->_primaryKey && !$attribute->_table && !$attribute->_setOnly && !$attribute->isEntity() && !$attribute->_isFile && !$attribute->getMappedAttributes() && !$attribute->_skipPersistence}
    if ($record->get{$attribute->getMethodName()}()) {ldelim}
{if $attribute->_mappedTo}
      $attr = {if $attribute->_useReference}&{/if}$record->getAttribute('{$attribute->_mappedTo}');
      $attr = $attr->get{$attribute->_columnMapping->getMethodName()}();
{/if}
{if $attribute->_type eq $smarty.const.SRA_DATA_TYPE_STRING}
      $sql .= " AND {$attribute->_column} LIKE {if $attribute->_setFunction}{$attribute->_setFunction}({/if}" . $record->getAttrDbValue('{$attribute->_name}', $sstr . {if $attribute->_mappedTo}$attr{else}$record->get{$attribute->getMethodName()}(){/if} . $sstr){if $attribute->_setFunction} . ')'{/if};
{else}
      $sql .= " AND {$attribute->_column} LIKE {if $attribute->_setFunction}{$attribute->_setFunction}({/if}" . $record->getAttrDbValue('{$attribute->_name}', {if $attribute->_mappedTo}$attr{else}$record->get{$attribute->getMethodName()}(){/if}){if $attribute->_setFunction} . ')'{/if};
{/if}
    {rdelim}
{/if}
{/foreach}
    {if $entity->_orderBy}$sql .= " ORDER BY {$entity->_orderBy}";{/if}
    {include file="entity-aspect-after.tpl"}
    return $this->_find($sql, $limit, $offset);
    
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} _find
  /**
   * private method is used by other find methods to lookup {$entity->_name} objects
   * @param mixed $context the query context. this will be one of the following:
   *                scalar: return {$entity->_name} with primary key of $context
   *                False: return all {$entity->_name} objects in the db
   *                array: each element in array is a {$entity->_name} primary key
   *                query: a SELECT query that returns {$entity->_name} primary keys
   * @param int $limit INTERNAL USE ONLY, DO NOT USE
   * @param int $offset INTERNAL USE ONLY, DO NOT USE
   * @param boolean $leftJoin INTERNAL USE ONLY, DO NOT USE
   * @param string $altModel an alternate VO to initialize. this class MUST be 
   * a subclass of {$voClassName}
   * @param array $altModelInitVals an associative array of init values that 
   * apply to the $altModel class specified. these will be added to the base 
   * init values for the {$voClassName}
   * @param boolean $reload whether or not to ignore any cached versions of the object
   * @access  private
   * @return {$voClassName}
   */
  function &_find($context, $limit=NULL, $offset=NULL, $leftJoin=FALSE, $altModel=FALSE, $altModelInitVals=FALSE, $reload=FALSE) {ldelim}
    {$Template->assign('aopMethodName', "_find")}
    {include file="entity-aspect-before.tpl"}
    // check if altModel class is valid
    if ($altModel && !class_exists($altModel)) {ldelim}
      $msg = "{$className}::_find: Failed - altModel '${ldelim}altModel{rdelim}' specified is not a valid class";
      {include file="entity-aspect-after.tpl"}
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    
    // if altModel specified, then altModelInitVals must also be specified
    if ($altModel && !is_array($altModelInitVals)) {ldelim}
      $msg = "{$className}::_find: Failed - altModel '${ldelim}altModel{rdelim}' specified but not altModelInitVals";
      {include file="entity-aspect-after.tpl"}
      return SRA_Error::logError($msg, __FILE__, __LINE__);    
    {rdelim}
    
    // check cache
    $results = array();
    if (!isset($this->_cacheResults)) {ldelim}
      $this->_cacheResults = array();
    {rdelim}
    if (is_array($context)) {ldelim}
      foreach ($context as $pk) {ldelim}
        if (array_key_exists($pk, $this->_cacheResults) && !$reload) {ldelim}
          $results[] =& $this->_cacheResults[$pk];
          unset($context[$pk]);
        {rdelim}
      {rdelim}
      if (!count($context)) {ldelim}
        {include file="entity-aspect-after.tpl"}
        return $results;
      {rdelim}
    {rdelim}
    else if (array_key_exists($context, $this->_cacheResults) && !$reload) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return $this->_cacheResults[$context];
    {rdelim}
    
    $daos =& $this->getDaos();
    $selectConstraint = FALSE;
    $orderConstraint = '';
    $selectTables = '{$entity->_table}';
    $colPreFunc = FALSE;

    if (strstr(strtolower($context), 'select ')) {ldelim}
      $parseQuery = SRA_Database::parseQuery($context);
      if (!in_array('{$entity->_table}', array_keys($parseQuery['from']))) {ldelim}
        $selectKeys = array_keys($parseQuery['select']);
        $fromKeys = array_keys($parseQuery['from']);
        $selectKeys = array_keys($parseQuery['select']);
        $parseQuery['from']['{$entity->_table}'] = '{$entity->_table}';
        $idCol = $selectKeys[0];
        $idColPieces = explode('.', $idCol);
        $idTable = $fromKeys[0];
        if (count($idColPieces) == 2) {ldelim}
          foreach ($fromKeys as $fromKey) {ldelim}
            if ($idColPieces[0] == $fromKey || $idColPieces[0] == $parseQuery['from'][$fromKey]) {ldelim}
              $idTable = $fromKey;
            {rdelim}
          {rdelim}
        {rdelim}
        else {ldelim}
          $idCol = "${ldelim}idTable{rdelim}.${ldelim}idCol{rdelim}";
        {rdelim}
        if ($idTable != $parseQuery['from'][$idTable]) {ldelim}
          $idTable .= ' AS ' . $parseQuery['from'][$idTable];
        {rdelim}
        if ($leftJoin && $idTable != '{$entity->_table}') {ldelim}
          $parseQuery['fromConstraints'][$idTable] = "LEFT JOIN ${ldelim}idTable{rdelim} ON {$entity->_table}.{$primaryKey->_column}=${ldelim}idCol{rdelim}";
        {rdelim}
        else {ldelim}
          $baseConstraint = $parseQuery['constraint'];
          $parseQuery['constraint'] = "{$entity->_table}.{$primaryKey->_column}=${ldelim}idCol{rdelim}";
          if ($baseConstraint) {ldelim}
            $parseQuery['constraint'] = $parseQuery['constraint'] . ' AND ' . $baseConstraint;
          {rdelim}
        {rdelim}
      {rdelim}
      $selectTables = '';
      $started = FALSE;
      $tkeys = array_keys($parseQuery['from']);
      foreach ($tkeys as $tkey) {ldelim}
        if (!isset($parseQuery['fromConstraints'][$tkey])) {ldelim}
          if ($started) {ldelim}
            $selectTables .= ', ';
          {rdelim}
          $selectTables .= $tkey;
          if ($tkey != $parseQuery['from'][$tkey]) {ldelim}
            $selectTables .= ' ' . $parseQuery['from'][$tkey];
          {rdelim}
          $started = TRUE;
        {rdelim}
      {rdelim}
      foreach ($tkeys as $tkey) {ldelim}
        if (isset($parseQuery['fromConstraints'][$tkey])) {ldelim}
          $selectTables .= ' ' . $parseQuery['fromConstraints'][$tkey];
        {rdelim}
      {rdelim}
      $selectConstraint = $parseQuery['constraint'];
      if ($leftJoin) {ldelim}
        if (!strstr('group by {$entity->_table}.{$primaryKey->_column}', strtolower($parseQuery['orderConstraint'])) && !strstr('group by {$primaryKey->_column}', strtolower($parseQuery['orderConstraint']))) {ldelim}
          $orderConstraint = ' GROUP BY {$entity->_table}.{$primaryKey->_column}';
        {rdelim}
        $colPreFunc = 'max';
      {rdelim}
      $orderConstraint .= ' ' . $parseQuery['orderConstraint'];
    {rdelim}
    else if (is_array($context)) {ldelim}
      $selectConstraint = "{$primaryKey->_column} IN (";
      $started = FALSE;
      foreach ($context as $pk) {ldelim}
        if ($started) {ldelim}
          $selectConstraint .= ', ';
        {rdelim}
        $selectConstraint .= $this->_db->{$primaryKey->getConvertMethodName()}($pk);
        $started = TRUE;
      {rdelim}
      $selectConstraint .= ')';
    {rdelim}
    else if ($context) {ldelim}
      $selectConstraint = "{$primaryKey->_column} = " . $this->_db->{$primaryKey->getConvertMethodName()}($context);
    {rdelim}
{if $entity->_constraint}
    if ($selectConstraint) {ldelim}
      $selectConstraint .= ' AND ';
    {rdelim}
    $selectConstraint .= "{$entity->_constraint}";
{/if}
    if ($selectConstraint) {ldelim}
      $selectConstraint = 'WHERE ' . trim($selectConstraint);
    {rdelim}
    $colPre = '';
    if ($selectTables != '{$entity->_table}') {ldelim}
      $colPre = '{$entity->_table}.';
    {rdelim}
    $selectClause = '';
{assign var="started" value="0"}
{foreach from=$entity->getAttributes() item=attribute}
{if (!$attribute->_table || $attribute->_table eq $entity->_table) && !$attribute->_lazyLoadExclusive && !$attribute->_tablePkColumn && !$attribute->_setOnly && !$attribute->getMappedAttributes() && (!$attribute->_cardinality || $attribute->_aggregateCardinality) && !$attribute->_skipPersistence}
{if $started}
    $selectClause .= ', ';
{/if}
{if $attribute->_name != $primaryKey->_name}
    if ($colPreFunc) {ldelim}
      $selectClause .= "${ldelim}colPreFunc{rdelim}(";
    {rdelim}
{/if}
{if $attribute->_retrieveFunction}
    $selectClause .= "{$attribute->_retrieveFunction}(${ldelim}colPre{rdelim}{$attribute->_column})";
    $asClause = '{$attribute->_column}';
{else}
    $selectClause .= "${ldelim}colPre{rdelim}{$attribute->_column}";
    $asClause = '';
{/if}
{if $attribute->_name != $primaryKey->_name}
    if ($colPreFunc) {ldelim}
      $selectClause .= ')';
    {rdelim}
{/if}
    if ($colPre) {ldelim}
      $selectClause .= ' AS ';
      $selectClause .= $asClause ? $asClause : '{$attribute->_column}';
    {rdelim}
    else if ($asClause) {ldelim}
      $selectClause .= ' AS ' . $asClause;
    {rdelim}
{assign var="started" value="1"}
{elseif $attribute->getMappedAttributes()}
{foreach from=$attribute->getMappedAttributes() item=attr}
{assign var="col" value=$attr->_column}
{if $started}
    $selectClause .= ', ';
{/if}
    if ($colPreFunc) {ldelim}
      $selectClause .= "${ldelim}colPreFunc{rdelim}(";
    {rdelim}
{if $attr->_retrieveFunction}
    $selectClause .= "{$attr->_retrieveFunction}(${ldelim}colPre{rdelim}{$col})";
    $asClause = '{$col}';
{else}
    $selectClause .= "${ldelim}colPre{rdelim}{$col}";
    $asClause = '';
{/if}
    if ($colPreFunc) {ldelim}
      $selectClause .= ')';
    {rdelim}
    if ($colPre) {ldelim}
      $selectClause .= ' AS ';
      $selectClause .= $asClause ? $asClause : '{$col}';
    {rdelim}
    else if ($asClause) {ldelim}
      $selectClause .= ' AS ' . $asClause;
    {rdelim}
{/foreach}
{assign var="started" value="1"}
{/if}
{/foreach}
    $sql = "SELECT ${ldelim}selectClause{rdelim} FROM ${ldelim}selectTables{rdelim} ${ldelim}selectConstraint{rdelim} ${ldelim}orderConstraint{rdelim}";
{if $entity->_orderBy}
    if (!strstr(strtolower($context), 'order by')) {ldelim}
      $sql .= " ORDER BY {$entity->_orderBy}";
    {rdelim}
{/if}
    
    // check for circular references
    if (isset($this->_cacheResults[$sql]) && !$reload) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return $this->_cacheResults[$sql];
    {rdelim}
    
    if (SRA_Error::isError($rows =& $this->_db->fetch($sql, array({assign var="started" value="0"}{foreach from=$entity->getAttributes() item=attribute}{if !$attribute->_table && !$attribute->_skipPersistence && !$attribute->_setOnly && !$attribute->getMappedAttributes() && (!$attribute->_cardinality || $attribute->_aggregateCardinality) && (!$attribute->_lazyLoad || ($attribute->_lazyLoad && (!$attribute->_table || ($attribute->_table eq $entity->_table)))) && !$attribute->_lazyLoadExclusive && !$attribute->_tablePkColumn}{if $started}, {/if}{if $attribute->_isFile && $entity->_fileHandling eq $smarty.const.SRA_FILE_ATTRIBUTE_TYPE_DB}SRA_DATA_TYPE_BLOB{elseif $attribute->_isFile && $entity->_fileHandling eq $smarty.const.SRA_FILE_ATTRIBUTE_TYPE_DIR}SRA_DATA_TYPE_STRING{elseif !$attribute->isEntity()}'{$attribute->_type}'{else}$daos['{$attribute->_name}']->getPkType(){/if}{assign var="started" value="1"}{elseif $attribute->getMappedAttributes()}{foreach from=$attribute->getMappedAttributes() item=attr}{if $started}, {/if}{if $attr->_isFile && $entity->_fileHandling eq $smarty.const.SRA_FILE_ATTRIBUTE_TYPE_DB}SRA_DATA_TYPE_BLOB{elseif $attr->_isFile && $entity->_fileHandling eq $smarty.const.SRA_FILE_ATTRIBUTE_TYPE_DIR}SRA_DATA_TYPE_STRING{elseif !$attr->isEntity()}'{$attr->_type}'{/if}{assign var="started" value="1"}{/foreach}{/if}{/foreach}), $limit, $offset))) {ldelim}
      $msg = "{$className}::_find: Failed - SRA_Database query '${ldelim}sql{rdelim}' resulted in an SRA_Error";
      {include file="entity-aspect-after.tpl"}
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    
    $resultCount = $rows->count();
    $totalResultCount = $rows->getTotalCount();
    
    // check for single result
    if ($rows->count() == 0) {ldelim}
      if ($context === FALSE || is_array($context) || strstr(strtolower($context), 'select ')) {ldelim}
        {include file="entity-aspect-after.tpl"}
        return array();
      {rdelim}
      else {ldelim}
        {include file="entity-aspect-after.tpl"}
        return FALSE;
      {rdelim}
    {rdelim}
    
    // create new {$voClassName}
    $count = -1;
    $includedPks = array();
    if (($context === FALSE || is_array($context)) && is_array($altModelInitVals)) {ldelim}
      $altModelInitKeys = array_keys($altModelInitVals);
    {rdelim}
    else if (is_array($altModelInitVals)) {ldelim}
      $altModelInitKeys = array(0);
      $altModelInitVals = array($altModelInitVals);
    {rdelim}
    while ($row =& $rows->next(TRUE)) {ldelim}
      // entity has already been added to results
      if (in_array($row[$this->getPkColumn()], $includedPks)) {ldelim}
        continue;
      {rdelim}
      
      $this->_cacheResults[$row[$this->getPkColumn()]] = SRA_ENTITY_ATTRIBUTE_CIRC_REF;
      
      $count++;
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->getMappedAttributes()}
      ${$attribute->_name}InitVals = array({foreach from=$attribute->getMappedAttributes() item=attr}{assign var="col" value=$attr->_column}'{$attr->_name}' => $row['{$col}'], {/foreach});
{/if}
{/foreach}
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_mappedTo}
      ${$attribute->_mappedTo}InitVals['{$attribute->_columnMapping->_attribute}'] = {if $attribute->_isFile}SRA_FileAttribute::getInstanceFromDb($row['{$attribute->_column}'], '{$attribute->_name}', FALSE, '{$entity->_name}', $row['{$primaryKey->_column}'], '{$entity->_fileDir}', '{$entity->_fileDirUri}', '{$entity->_fileHandling}', '{$entity->_fileScriptRewrite}', '{$entity->_fileScriptUri}'){elseif !$attribute->isEntity()}$row['{$attribute->_column}']{else}$daos['{$attribute->_name}']->findByPk($row['{$attribute->_column}']){/if};
{/if}
{/foreach}
      $initVals = array({assign var="started" value="0"}{foreach from=$entity->getAttributes() item=attribute}{if !$attribute->_lazyLoad && !$attribute->_lazyLoadExclusive && !$attribute->_setOnly && !$attribute->_mappedTo && (!$attribute->_cardinality || $attribute->_aggregateCardinality) && !$attribute->_table && !$attribute->_skipPersistence}{if $started}, {/if}'{$attribute->_name}' => {if $attribute->getMappedAttributes()}new {$attribute->_type}{$entity->_voSuffix}(${$attribute->_name}InitVals, FALSE){elseif $attribute->_isFile}SRA_FileAttribute::getInstanceFromDb($row['{$attribute->_column}'], '{$attribute->_name}', FALSE, '{$entity->_name}', $row['{$primaryKey->_column}'], '{$entity->_fileDir}', '{$entity->_fileDirUri}', '{$entity->_fileHandling}', '{$entity->_fileScriptRewrite}', '{$entity->_fileScriptUri}'){elseif !$attribute->isEntity()}{if $attribute->_aggregateCardinality}$row['{$attribute->_column}'] ? explode('{$smarty.const.SRA_AGGREGATE_CARDINALITY_DELIM}', {/if}$row['{$attribute->_column}']{if $attribute->_aggregateCardinality}) : NULL{/if}{else}$daos['{$attribute->_name}']->findByPk($row['{$attribute->_column}']){/if}{assign var="started" value="1"}{/if}{/foreach});
      {foreach from=$entity->getAttributes() item=attribute}
      {if !$attribute->isEntity() && $attribute->_aggregateCardinality}
      if ($initVals['{$attribute->_name}'] === NULL) {ldelim} unset($initVals['{$attribute->_name}']); {rdelim}
      {/if}
      {/foreach}
      if ($altModel) {ldelim}
        $results[$count] = new ${ldelim}altModel{rdelim}(array_merge($initVals, $altModelInitVals[$altModelInitKeys[$count]]), FALSE);
        // validate altModel
        if (!{$voClassName}::isValid($results[$count])) {ldelim}
          $msg = "{$className}::_find: Failed - altModel '${ldelim}altModel{rdelim}' specified is not a subclass of {$voClassName}";
          {include file="entity-aspect-after.tpl"}
          return SRA_Error::logError($msg, __FILE__, __LINE__);
        {rdelim}
      {rdelim}
      else {ldelim}
        require_once('{$voClassName}.{$smarty.const.SRA_SYS_PHP_EXTENSION}');
        $results[$count] = new {$voClassName}($initVals, FALSE, TRUE);
      {rdelim}
      
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_lazyLoad && !$attribute->_table && $attribute->_column && (!$attribute->_cardinality || $attribute->_aggregateCardinality)}
      $results[$count]->_lazyLoadPks['{$attribute->_name}'] = {if $attribute->_aggregateCardinality}explode('{$smarty.const.SRA_AGGREGATE_CARDINALITY_DELIM}', {/if}$row['{$attribute->_column}']{if $attribute->_aggregateCardinality}){/if};
{elseif !$attribute->_lazyLoad && ($attribute->_table || (!$attribute->_table && $attribute->_type && $attribute->_cardinality && !$attribute->_aggregateCardinality))}
      // set relational {$attribute->_name} attribute
      $attr = $this->get{$attribute->getMethodName()}($results[$count]);
{if $attribute->_cardinality}
      if (is_array($attr) && count($attr)) {ldelim}
{else}
      if ($attr) {ldelim}
{/if}
        $results[$count]->set{$attribute->getMethodName()}($attr, FALSE);
      {rdelim}
{/if}
{/foreach}
      
      $includedPks[] = $results[$count]->getPrimaryKey();
      
      // cache results
      $this->_cacheResults[$results[$count]->getPrimaryKey()] = $results[$count];
      
    {rdelim}
    
    // cache query results
    if (strstr(strtolower($context), 'select ')) {ldelim}
      $this->_cacheResults[$context] = $results;
    {rdelim}
    else if (strstr(strtolower($sql), 'select ')) {ldelim}
      $this->_cacheResults[$sql] = $results;
    {rdelim}
    
    $this->resultCount = $resultCount;
    $this->totalResultCount = $totalResultCount;
    
    if ($context === FALSE || is_array($context) || strstr(strtolower($context), 'select ')) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return $results;
    {rdelim}
    else {ldelim}
      {include file="entity-aspect-after.tpl"}
      return $results[0];
    {rdelim}
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} getAppDbEntityKeys
  /**
   * This method returns an associative array of all of the entity database 
   * primary key values converted into a db prepared format 
   * 
   * @param {$voClassName} $record the {$voClassName} to return the keys for
   * @access  public
   * @return array
   */
  function &getAppDbEntityKeys(& $record) {ldelim}
    {$Template->assign('aopMethodName', "getAppDbEntityKeys")}
    {include file="entity-aspect-before.tpl"}
    $dbEntityKeys = array();
{foreach from=$entity->getAttributes() item=attribute}
{if !$attribute->_table && $attribute->isEntity() && !$attribute->getMappedAttributes()}
    if (${$attribute->_name} = $record->get{$attribute->getMethodName()}()) {ldelim}
{if $attribute->_typeExtends}
      $dao =& SRA_DaoFactory::getDao('{$attribute->_typeExtends}');
{else}
      $dao =& SRA_DaoFactory::getDao('{$attribute->_type}');
{/if}
      // insert record if necessary
      if (!${$attribute->_name}->recordExists) {ldelim}
        ${$attribute->_name} =& $dao->insert(${$attribute->_name});
      {rdelim}
      $dbEntityKeys['{$attribute->_name}'] = $dao->convertPk(${$attribute->_name}->getPrimaryKey());
    {rdelim}
    else {ldelim}
      $dbEntityKeys['{$attribute->_name}'] = '';
    {rdelim}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
    return $dbEntityKeys;
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} getDaos
  /**
   * This method returns an associative array of all of the external DAOs 
   * referenced by attributes of the entity this DAO manages
   * @access  public
   * @return DataAccessObject[]
   */
  function &getDaos() {ldelim}
    {$Template->assign('aopMethodName', "getDaos")}
    {include file="entity-aspect-before.tpl"}
    
    if (!isset($this->_daos)) {ldelim}
      $this->_daos = array();
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->isEntity() && !$attribute->getMappedAttributes()}
{if $attribute->_typeExtends}{assign var='aType' value=$attribute->_typeExtends}{else}{assign var='aType' value=$attribute->_type}{/if}
      $this->_daos['{$attribute->_name}'] =& {if $aType eq $entity->_name}$this{else}SRA_DaoFactory::getDao('{$aType}', TRUE){/if};
{if $attribute->_nestedType}
{foreach from=$attribute->_attributeGenerators item=nattribute}
{if $nattribute->isEntity() && !$nattribute->_nestedType && !$nattribute->getMappedAttributes()}
      $this->_daos['{$attribute->_name}::{$nattribute->_name}'] =& SRA_DaoFactory::getDao('{if $nattribute->_typeExtends}{$nattribute->_typeExtends}{else}{$nattribute->_type}{/if}');
{/if}
{/foreach}
{/if}
{/if}
{/foreach}
    {rdelim}
    {include file="entity-aspect-after.tpl"}
    return $this->_daos;
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} getPkColumn
  /**
   * This method returns the database column name for the primary key of the 
   * entity managed by this DAO.
   * @access  public
   * @return string
   */
  function getPkColumn() {ldelim}
    {$Template->assign('aopMethodName', "getPkColumn")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    return '{$primaryKey->_column}';
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} getPkName
  /**
   * This method returns the name of the primary key for the entity managed by 
   * this DAO.
   * @access  public
   * @return string
   */
  function getPkName() {ldelim}
    {$Template->assign('aopMethodName', "getPkName")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    return '{$primaryKey->_name}';
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} getPkType
  /**
   * This method returns the database type for the primary key of the entity 
   * managed by this DAO. This value will correspond with one of the SRA_Database 
   * class type constants
   * @access  public
   * @return string
   */
  function getPkType() {ldelim}
    {$Template->assign('aopMethodName', "getPkType")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    return '{$primaryKey->_type}';
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} convertAttributeValue
  /**
   * converts an attribute value into the appropriate database format
   * @param string $attribute the name of the attribute that this value is for
   * @param mixed $value the attribute value to convert
   * @access  public
   * @return string
   */
  function convertAttributeValue($attribute, $value) {ldelim}
    {$Template->assign('aopMethodName', "convertAttributeValue")}
    {include file="entity-aspect-before.tpl"}
    $db =& SRA_Controller::getAppDb({if $entity->_db}'{$entity->_db}'{/if});
    $daos =& $this->getDaos();
    // attribute specific table
{foreach from=$entity->getAttributes() item=attribute}
    if ($attribute == '{$attribute->_name}') {ldelim}
{if !$attribute->isEntity()}
{if $attribute->_type eq ($attribute->_type eq $smarty.const.SRA_DATA_TYPE_DATE || $attribute->_type eq $smarty.const.SRA_DATA_TYPE_TIME)}
      if (is_scalar($value)) {ldelim}
        $value = new SRA_GregorianDate($value);
      {rdelim}
{/if}
      {include file="entity-aspect-after.tpl"}
      return $db->{$attribute->getConvertMethodName()}($value);
{elseif !$attribute->getMappedAttributes()}
      {include file="entity-aspect-after.tpl"}
      return $daos['{$attribute->_name}']->convertAttributeValue($daos['{$attribute->_name}']->getPkName(), $value);
{/if}
    {rdelim}
{if $attribute->getAggregateAttributes()}
{foreach from=$attribute->getAggregateAttributes() item=attr}
    if ($attribute == '{$attr->_name}') {ldelim}
{if $attribute->_type eq $smarty.const.SRA_DATA_TYPE_DATE || $attribute->_type eq $smarty.const.SRA_DATA_TYPE_TIME}
      if (is_scalar($value)) {ldelim}
        $value = new SRA_GregorianDate($value);
      {rdelim}
{/if}
      {include file="entity-aspect-after.tpl"}
      return $db->{$attr->getConvertMethodName()}($value);
    {rdelim}
{/foreach}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
    return FALSE;
  {rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} getColumnName
  /**
   * returns the column name for the specified attribute. this method can only 
   * be called for scalar attributes
   * @param string $attribute the name of the attribute to return the column 
   * name for. if not specified, the primary key column name will be returned
   * @access  public
   * @return string
   */
  function getColumnName($attribute = FALSE) {ldelim}
    {$Template->assign('aopMethodName', "getColumnName")}
    {include file="entity-aspect-before.tpl"}
    // base entity table
    if (!$attribute) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return '{$primaryKey->_column}';
    {rdelim}
    // attribute specific table
    $daos =& $this->getDaos();
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_column && !$attribute->_skipPersistence && !$attribute->getMappedAttributes()}
    if ($attribute == '{$attribute->_name}') {ldelim}
      {include file="entity-aspect-after.tpl"}
      return '{$attribute->_column}';
    {rdelim}
{elseif $attribute->getMappedAttributes() && $attribute->getAggregateAttributes()}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{if $attr->_column && !$attr->_skipPersistence}
    if ($attribute == '{$attr->_name}') {ldelim}
      {include file="entity-aspect-after.tpl"}
      return '{$attr->_column}';
    {rdelim}
{/if}
{/foreach}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
    return FALSE;
  {rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} getSortColumnName
  /**
   * returns the name of the column(s) that should be sorted on whenever the 
   * $attribute specified is included in a sort constraint for a query. this 
   * value is specified in the entity model using the attribute tag "sort-columns" 
   * typically, for attributes that exist in the primary entity table, this 
   * value will be the same as the column that represents them. however, if 
   * the attribute exists in a foreign table, the name of the column in that 
   * table that represents the attribute may be explicitely specified. if the 
   * $attribute is an entity and "sort-columns" is not specified in the entity 
   * model, but "column" is, then the value of "column" will be returned. if 
   * $attribute is not specified or is not an entity and does not have a 
   * "sort-column" defined, and a "sort-columns" value is specified for the 
   * entity this DAO represents (a default entity sort column for example), then 
   * that "sort-columns" value will be returned. if the $attribute is an entity, 
   * and no "sort-column" has been specified, then the "getSortColumnName" 
   * method will be invoked on that attribute's corresponding entity DAO. 
   * otherwise, FALSE will be returned. 
   * @param string $attribute the attribute for which the sort column should be returned
   * @param string $tableName optional table name to append to each of the sort 
   * column names (i.e. $tableName.$sortColumnName)
   * @access  public
   * @return string
   */
  function getSortColumnName($attribute = FALSE, $tableName = FALSE) {ldelim}
    {$Template->assign('aopMethodName', "getSortColumnName")}
    {include file="entity-aspect-before.tpl"}
    $sortColumns = FALSE;
    $daos =& $this->getDaos();
{foreach from=$entity->getAttributes() item=attribute}
{if !$attribute->isEntity() && $attribute->_column && !$attribute->_skipPersistence}
    if ($attribute == '{$attribute->_name}') {ldelim}
{if $attribute->_orderBy}
      $sortColumns = '{$attribute->_orderBy}';
{if $attribute->isEntity()}
      if ($tableName) {ldelim}
        $tableName = $daos['{$attribute->_name}']->getTableName();
      {rdelim}
{/if}
{else}
      $sortColumns = '{$attribute->_column}';
{/if}
    {rdelim}
{/if}
{/foreach}
    if (!$sortColumns) {ldelim}
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->isEntity() && !$attribute->getMappedAttributes()}
      if ($attribute == '{$attribute->_name}') {ldelim}
        {include file="entity-aspect-after.tpl"}
        return $daos['{$attribute->_name}']->getSortColumnName();
      {rdelim}
{elseif $attribute->getMappedAttributes() && $attribute->getAggregateAttributes()}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{if $attr->_column && !$attr->_skipPersistence}
    if ($attribute == '{$attr->_name}') {ldelim}
{if $attr->_orderBy}
      $sortColumns = '{$attr->_orderBy}';
{else}
      $sortColumns = '{$attr->_column}';
{/if}
    {rdelim}
{/if}
{/foreach}
{/if}
{/foreach}
    {rdelim}
{if $entity->_orderBy}
    if (!$sortColumns) {ldelim}
      $sortColumns = '{$entity->_orderBy}';
    {rdelim}
{/if}
    if ($sortColumns && $tableName) {ldelim}
      $started = FALSE;
      $sortColumns = explode(',', $sortColumns);
      $tmp = '';
      foreach ($sortColumns as $sortColumn) {ldelim}
        if ($started) {ldelim}
          $tmp .= ',';
        {rdelim}
        $tmp .= ' ' . $tableName . '.' . trim($sortColumn);
        $started = TRUE;
      {rdelim}
      $sortColumns = $tmp;
    {rdelim}
    {include file="entity-aspect-after.tpl"}
    return $sortColumns;
  {rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} getTableName
  /**
   * This method returns the database type table name of the entity managed by 
   * this DAO. if $attribute is specified, the following results may be returned:
   *   1) if attribute is in primary entity table: entity table name returned 
   *     same as calling without attribute
   *  2) if attribute exists in external table:
   *     a) if external table contains entity pk foreign key:
   *          return array('table' => 'external table name', 'pkColumn' => 'external table column name for entity pk')
   * this method can only be called for scalar attributes
   * @param string $attribute the name of the attribute to return the table name 
   * for. if not specified, the entity table name will be returned
   * @access  public
   * @return string
   */
  function getTableName($attribute = FALSE) {ldelim}
    {$Template->assign('aopMethodName', "getTableName")}
    {include file="entity-aspect-before.tpl"}
    // attribute specific table
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_table != $entity->_table && $attribute->_table && $attribute->_column}
    if ($attribute == '{$attribute->_name}') {ldelim}
      {include file="entity-aspect-after.tpl"}
      return array('table' => '{$attribute->_table}', 'pkColumn' => '{if $attribute->_tablePkColumn}{$attribute->_tablePkColumn}{else}{$primaryKey->_column}{/if}');
    {rdelim}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
    return '{$entity->_table}';
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
{foreach from=$entity->getAttributes() item=attribute}
{if !$attribute->getMappedAttributes() && ($attribute->_lazyLoad || $attribute->_lazyLoadExclusive || $attribute->_table || (!$attribute->_table && $attribute->_type && $attribute->_cardinality))}
{assign var="methodName" value="get"|cat:$attribute->getMethodName()}

  // {ldelim}{ldelim}{ldelim} {$methodName}
  /**
   * This method returns the {$attribute->_name} attribute for a given {$entity->_name}
   * @param {$entity->_type} $record the {$entity->_type} instance to return the 
   * {$attribute->_name} for
{if $attribute->_cardinality && $attribute->isEntity()}
   * @param mixed $pk if only a single {$attribute->_name} should be returned, 
   * this parameter may be specified as the primary key of that object
{/if}
   * @access  public
   * @return {$attribute->_type}{if $attribute->_cardinalityUpper > 1}[]
{/if}
   */
  function {if $attribute->_useReference}&{/if}{$methodName}(& $record{if $attribute->_cardinality && $attribute->isEntity()}, $pk = FALSE{/if}) {ldelim}
    
    {$Template->assign('aopMethodName', $methodName)}
    {include file="entity-aspect-before.tpl"}
{if !$attribute->_table}
    $daos =& $this->getDaos();
{if !$attribute->_cardinality && !$attribute->_tablePkColumn}
{if $attribute->_column && !$attribute->_table || $attribute->_table == $entity->_table}
{if $attribute->isEntity()}
    if (isset($daos['{$attribute->_name}']) && isset($record->_lazyLoadPks) && isset($record->_lazyLoadPks['{$attribute->_name}'])) {ldelim}
      return $daos['{$attribute->_name}']->findByPk($record->_lazyLoadPks['{$attribute->_name}']);
    {rdelim}
{/if}
    $db =& SRA_Controller::getAppDb({if $entity->_db}'{$entity->_db}'{/if});
    $sql = 'SELECT {$attribute->_column} FROM {$entity->_table} WHERE {$primaryKey->_column} = ' . $record->getAttrDbValue();
    $result =& $db->fetch($sql, array('{if $attribute->isEntity()}{$primaryKey->_type}{else}{$attribute->_type}{/if}'));
    if (SRA_ResultSet::isValid($result) && count($result)) {ldelim}
      $row =& $result->next();
{if $attribute->_isFile}
      {include file="entity-aspect-after.tpl"}
      return SRA_FileAttribute::getInstanceFromDb($row[0], '{$attribute->_name}', FALSE, '{$entity->_name}', $record->getPrimaryKey(), '{$entity->_fileDir}', '{$entity->_fileDirUri}', '{$entity->_fileHandling}', '{$entity->_fileScriptRewrite}', '{$entity->_fileScriptUri}');
{else}
      {include file="entity-aspect-after.tpl"}
      return {if $attribute->isEntity()}$row[0] ? $daos['{$attribute->_name}']->findByPk({/if}$row[0]{if $attribute->isEntity()}) : $row[0]{/if};
{/if}
    {rdelim}
    {include file="entity-aspect-after.tpl"}
    return null;
{else}
    {include file="entity-aspect-after.tpl"}
    return $daos['{$attribute->_name}']->findByPk($record->_lazyLoadPks['{$attribute->_name}']);
{/if}
{else}
    if (!isset($this->_{$attribute->_name}Cache)) {ldelim}
      $this->_{$attribute->_name}Cache = array();
      $this->_{$attribute->_name}CacheRetrieved = array();
    {rdelim}
    if (!$this->_{$attribute->_name}CacheRetrieved[$record->getPrimaryKey()]) {ldelim}
      $this->_{$attribute->_name}CacheRetrieved[$record->getPrimaryKey()] = TRUE;
      $tmp =& $daos['{$attribute->_name}']->findBySqlConstraints(array('{if $attribute->_tablePkColumn}{$attribute->_tablePkColumn}{else}{$primaryKey->_column}{/if}' => $this->_db->{$primaryKey->getConvertMethodName()}($record->getPrimaryKey())), {if $attribute->_constraint}"{$attribute->_constraint}"{else}FALSE{/if}, {if $attribute->_orderBy}'{$attribute->_orderBy}'{else}FALSE{/if});
      $keys = array_keys($tmp);
{if $attribute->_cardinality}
      $this->_{$attribute->_name}Cache[$record->getPrimaryKey()] = array();
      foreach ($keys as $key) {ldelim}
        $this->_{$attribute->_name}Cache[$record->getPrimaryKey()][$tmp[$key]->getPrimaryKey()] =& $tmp[$key];
      {rdelim}
{else}
      if (count($keys)) {ldelim}
        $this->_{$attribute->_name}Cache[$record->getPrimaryKey()] = $tmp[$keys[0]];
      {rdelim}
{/if}
    {rdelim}
{if $attribute->_cardinality}
    if ($pk) {ldelim}
      if (!is_array($pk)) {ldelim}
        {include file="entity-aspect-after.tpl"}
        return isset($this->_{$attribute->_name}Cache[$record->getPrimaryKey()][$pk]) ? $this->_{$attribute->_name}Cache[$record->getPrimaryKey()][$pk] : FALSE;
      {rdelim}
      $matches = array();
      foreach ($pk as $key) {ldelim}
        if (isset($this->_{$attribute->_name}Cache[$record->getPrimaryKey()][$key])) {ldelim}
          $matches[$this->_{$attribute->_name}Cache[$record->getPrimaryKey()][$key]->getPrimaryKey()] =& $this->_{$attribute->_name}Cache[$record->getPrimaryKey()][$key];
        {rdelim}
      {rdelim}
      {include file="entity-aspect-after.tpl"}
      return $matches;
    {rdelim}
    else {ldelim}
      {include file="entity-aspect-after.tpl"}
      return $this->_{$attribute->_name}Cache[$record->getPrimaryKey()];
    {rdelim}
{else}
    {include file="entity-aspect-after.tpl"}
    return $this->_{$attribute->_name}Cache[$record->getPrimaryKey()];
{/if}
{/if}
{else}
    
    // check if param is a valid {$voClassName} instance
    if (!is_scalar($record) && !{$voClassName}::isValid($record)) {ldelim}
      {include file="entity-aspect-after.tpl"}
      $msg = "{$className}::get{$attribute->getMethodName()}: Failed - parameter is not a valid {$voClassName} instance or scalar primary key value";
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    
    // check if id is valid
    if (!is_scalar($record) && !$record->getPrimaryKey()) {ldelim}
      {include file="entity-aspect-after.tpl"}
      $msg = "{$className}::get{$attribute->getMethodName()}: Failed - No primary key specified";
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    
    if (is_scalar($record)) {ldelim}
      $rpk = $record;
    {rdelim}
    else {ldelim}
      $rpk = $record->getPrimaryKey();
    {rdelim}
    
{if $attribute->isEntity()}
    $daos =& $this->getDaos();
{/if}
{if $attribute->_typeExtends}
    $extendsDAO =& SRA_DaoFactory::getDao('{$attribute->_typeExtends}');
{/if}
{if $attribute->isEntity() && !$attribute->_nestedType}
    $sql = 'SELECT {$attribute->_table}.' . $daos['{$attribute->_name}']->getPkColumn() . ' FROM {$attribute->_table} WHERE {$attribute->_table}.{if $attribute->_tablePkColumn}{$attribute->_tablePkColumn}{else}{$primaryKey->_column}{/if} = ' . $this->_db->{$primaryKey->getConvertMethodName()}($rpk){if $attribute->_constraint} . " AND {$attribute->_constraint}"{/if};
{else}
    $sql = "SELECT {assign var="started" value="0"}{foreach from=$entity->getTableAttributes($attribute->_table) key=attr item=generator}{if !$generator->isEntity() && $generator->_column}{if $started}, {/if}{if $generator->_retrieveFunction}{$generator->_retrieveFunction}({$generator->_column}) AS {/if}{$generator->_column}{assign var="started" value="1"}{/if}{/foreach} FROM {$attribute->_table} WHERE {if $attribute->_tablePkColumn}{$attribute->_tablePkColumn}{else}{$primaryKey->_column}{/if} = " . $this->_db->{$primaryKey->getConvertMethodName()}($rpk){if $attribute->_constraint} . " AND {$attribute->_constraint}"{/if};
{/if}
{if $attribute->_cardinality && $attribute->isEntity()}
{if $attribute->_typeExtends}
    {assign var="pkVoClass" value=$attribute->_typeExtends|cat:$entity->_voSuffix}
{else}
     {assign var="pkVoClass" value=$attribute->_type|cat:$entity->_voSuffix}
{/if}
{if $attribute->isEntity() && $attribute->_cardinality}
    $returnFirst = $pk ? TRUE : FALSE;
    if ($pk && !is_array($pk)) {ldelim} $pk = array({$pkVoClass}::getPrimaryKeyAttribute() => $pk); {rdelim}
    if ($pk) {ldelim}
      foreach ($pk as $attr => $val) {ldelim}
        $sql .= ' AND {if $attribute->isEntity() && !$attribute->_nestedType}{$attribute->_table}.{/if}' . $daos['{$attribute->_name}']->getColumnName($attr) . '=' . {$pkVoClass}::getAttrDbValue($attr, $val);
      {rdelim}
    {rdelim}
{/if}
{/if}
{if $attribute->_orderBy}
    $sql .= " ORDER BY {$attribute->_orderBy}";
{/if}
{if $attribute->isEntity() && !$attribute->_nestedType}
    ${$attribute->_name} =& $daos['{$attribute->_name}']->findByQuery($sql);
{else}
    if (SRA_Error::isError($results =& $this->_db->fetch($sql, array({assign var="started" value="0"}{foreach from=$entity->getTableAttributes($attribute->_table) key=attr item=generator}{if !$generator->isEntity() && $generator->_column}{if $started}, {/if}'{$generator->_type}'{assign var="started" value="1"}{/if}{/foreach})))) {ldelim}
      {include file="entity-aspect-after.tpl"}
      $msg = "{$className}::get{$attribute->getMethodName()}: Failed - SRA_Database query '${ldelim}sql{rdelim}' resulted in an SRA_Error";
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}

{foreach from=$entity->getTableAttributes($attribute->_table) key=attr item=generator}
    ${$generator->_name} = NULL;
{/foreach}
    {if $attribute->_cardinality}while{else}if{/if} ($row =& $results->next(TRUE)) {ldelim}
{foreach from=$entity->getTableAttributes($attribute->_table) key=attr item=generator}
{if !$generator->isEntity() && $generator->_column}
      ${$generator->_name}{if $attribute->_cardinality}[]{/if} = $row['{$generator->_column}'];
{/if}
{/foreach}
{if $attribute->isEntity()}
{if $attribute->_nestedType}
      $initVals = array({assign var="started" value="0"}{foreach from=$attribute->_attributeGenerators item=nattribute}{if !$nattribute->_table && !$nattribute->_setOnly}{if $started}, {/if}'{$nattribute->_name}' => {if $nattribute->_isFile}SRA_FileAttribute::getInstanceFromDb($row['{$nattribute->_column}'], '{$attribute->_name}#{$nattribute->_name}', {if $attribute->_cardinality}count($attr){else}FALSE{/if}, '{$entity->_name}', $record->getPrimaryKey(), '{$nentity->_fileDir}', '{$nentity->_fileDirUri}', '{$nentity->_fileHandling}', '{$nentity->_fileScriptRewrite}', '{$nentity->_fileScriptUri}'){elseif !$nattribute->isEntity()}$row['{$nattribute->_column}']{else}$daos['{$attribute->_name}::{$nattribute->_name}']->findByPk($row['{$nattribute->_column}']){/if}{assign var="started" value="1"}{/if}{/foreach});
{if $attribute->_typeExtends}
      ${$attribute->_name}{if $attribute->_cardinality}[]{/if} =& $extendsDAO->_find($row[$extendsDAO->getPkColumn()], FALSE, FALSE, '{$attribute->getNestedVOName()}', $initVals);
{else}
      require_once('{$attribute->getNestedVOName()}.{$smarty.const.SRA_SYS_PHP_EXTENSION}');
      ${$attribute->_name}{if $attribute->_cardinality}[]{/if} = new {$attribute->getNestedVOName()}($initVals, FALSE);
{/if}
{else}
      ${$attribute->_name}{if $attribute->_cardinality}[]{/if} =& $daos['{$attribute->_name}']->findByPk($row[{if !$attribute->_tablePkColumn}$daos['{$attribute->_name}']->getPkColumn(){else}'{$attribute->_tablePkColumn}'{/if}]);
{/if}
      ${$attribute->_name}{if $attribute->_cardinality}[count($attr) - 1]{/if}->recordExists = TRUE;
{/if}
    {rdelim}
    
{foreach from=$entity->getTableAttributes($attribute->_table) key=attr item=generator}
{if !$generator->isEntity() && $generator->_column && $attribute->_name neq $generator->_name}
    if (${$generator->_name} != NULL && !$record->hasBeenSet('{$generator->_name}')) {ldelim}
      $record->set{$generator->getMethodName()}(${$generator->_name}, FALSE);
    {rdelim}
{/if}
{/foreach}
{/if}
{if $attribute->_cardinality}
{if $attribute->isEntity()}
    $keys = array_keys(${$attribute->_name});
    if ($returnFirst) {ldelim}
      $nl = NULL;
      return count($keys) ? ${$attribute->_name}[$keys[0]] : $nl;
    {rdelim}
    else {ldelim}
      $tmp = array();
      foreach ($keys as $key) {ldelim}
        if (is_object(${$attribute->_name}[$key])) {ldelim}
          $tmp[${$attribute->_name}[$key]->getPrimaryKey()] =& ${$attribute->_name}[$key];
        {rdelim}
      {rdelim}
      {include file="entity-aspect-after.tpl"}
      return $tmp;
    {rdelim}
{else}
    return ${$attribute->_name};
{/if}
{else}
    {include file="entity-aspect-after.tpl"}
    if (is_array(${$attribute->_name}) && count(${$attribute->_name})) {ldelim}
      return ${$attribute->_name}[0];
    {rdelim}
    else if (is_array($attr) && !count(${$attribute->_name})) {ldelim}
      return FALSE;
    {rdelim}
    else {ldelim}
      return ${$attribute->_name};
    {rdelim}
{/if}
{/if} {* !$attribute->_table *}
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
{/if}
{/foreach}
  
  
  // {ldelim}{ldelim}{ldelim} insert
  /**
   * This method is used to insert a new {$entity->_name} object into the 
   * persistency store managed by this DAO. If the {$entity->_name} uses an 
   * auto-sequence primary key, then the value of that primary key will be 
   * auto-set in the referenced {$voClassName} parameter. If the $record already 
   * exists, the update method will be invoked instead
   * @param {$voClassName} $record The {$entity->_name} instance to insert
   * @param boolean $updateSubEntities whether or not sub-entities should also 
   * be checked and inserted (only if they have been loaded)
   * @access  public
   * @return void
   */
  function insert(& $record, $insertSubEntities) {ldelim}
    {$Template->assign('aopMethodName', "insert")}
    {include file="entity-aspect-before.tpl"}
    // check if param is a valid {$voClassName} instance
    if (!{$voClassName}::isValid($record)) {ldelim}
      {include file="entity-aspect-after.tpl"}
      $msg = "{$className}::insert: Failed - parameter is not a valid {$voClassName} instance";
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    
    // does record already exist? if it does, pass to the update method
    if ($record->recordExists) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return $this->update($record, $insertSubEntities);    
    {rdelim}
    
    // validate {$voClassName}
    if (!$record->validate()) {ldelim}
      {include file="entity-aspect-after.tpl"}
      $msg = "{$className}::insert: Failed - {$voClassName} instance validation failed: " . implode(', ', $record->validateErrors);
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    
{if $primaryKey->_sequence}
    // validate primary key - cannot be set because it is a sequence
    if ($record->getPrimaryKey()) {ldelim}
      {include file="entity-aspect-after.tpl"}
      $msg = "{$className}::insert: Failed - Primary key " . $record->getPrimaryKey() . " already set for sequence. Object cannot be inserted";
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
{else}
    // validate primary key - must be set because it is not an auto-sequence
    if (!$record->getPrimaryKey()) {ldelim}
      {include file="entity-aspect-after.tpl"}
      $msg = "{$className}::insert: Failed - No primary key specified for this {$voClassName}";
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
{/if}
    
    // start transaction
    $completeTransaction = TRUE;
    if (!$this->_db->isInTransaction()) {ldelim}
      $this->_db->startTransaction();
    {rdelim}
    else {ldelim}
      $completeTransaction = FALSE;
    {rdelim}
    
    $sql =  'INSERT INTO {$primaryTable->getName()} ';
    
    // Add column definitions
    $started = FALSE;
    $firstAttr = FALSE;
    $firstCol = FALSE;
{foreach from=$primaryTable->getColumns() item=column}
{if !$entity->isFile($column->getBaseAttribute()) && $column->isWritable(1)}
    if ($record->isDirty('{$column->getBaseAttribute()}') || $record->getAttribute('{$column->getBaseAttribute()}') != NULL) {ldelim}
      $colConstraint .= $started ? ', ' : '';
      $colConstraint .= '{$column->getName()}';
      $valConstraint .= $started ? ', ' : '';
      $valConstraint .= {if $column->getSetFunction()}'{$column->getSetFunction()}(' . {/if}$record->getAttrDbValue('{$column->getBaseAttribute()}'){if $column->getSetFunction()} . ')'{/if};
      $started = TRUE;
    {rdelim}
    else if (!$started) {ldelim}
      $firstAttr = {if $column->getSetFunction()}'{$column->getSetFunction()}(' . {/if}$record->getAttrDbValue('{$column->getBaseAttribute()}'){if $column->getSetFunction()} . ')'{/if};
      $firstCol = '{$column->getName()}';
    {rdelim}
{/if}
{/foreach}

    // Add values
    $sql .= $started ? '(' . $colConstraint . ') VALUES (' . $valConstraint . ')' : '(' . $firstCol . ') VALUES (' . $firstAttr . ')';
    
    if (SRA_Error::isError($results =& $this->_db->execute($sql{if $primaryTable->primaryKeyIsSequence()}, '{$primaryTable->getPrimaryKey()}'{/if}))) {ldelim}
      if ($completeTransaction) {ldelim} $this->_db->rollback(); {rdelim}
      {include file="entity-aspect-after.tpl"}
      $msg = "{$className}::insert: Failed - SRA_Database query '${ldelim}sql{rdelim}' resulted in an SRA_Error";
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
{if $primaryTable->primaryKeyIsSequence()}
    $record->set{$primaryKey->getMethodName()}($results->getSequenceValue());
{/if}
    $record->recordExists = TRUE;
    
    // update relational values
{foreach from=$schema->getTables() item=table}
{* get each distinct group of attributes that utilize this table *}
{foreach from=$table->getAttributeGroups() item=attrs}
{assign var="hasCardinality" value="0"}
    
    if ($record->isDirty(array({foreach from=$attrs item=attr}{if !$entity->isPrimaryTableAttr($attr)}'{$attr}', {/if}{/foreach}))) {ldelim}
{assign var=renderBaseQuery value="0"}
{assign var=readConstraints value="0"}
{foreach from=$attrs key=attrId item=attr}
{if !$entity->isPrimaryTableAttr($attr) || $attr eq $primaryKey->_name}
{assign var=attribute value=$entity->getAttributes($attr)}
{if $attribute->_tablePkColumn}{assign var=pkColName value=$attribute->_tablePkColumn}{else}{assign var=pkColName value=$primaryKey->_column}{/if}
{if $attribute->_cardinality}{assign var="hasCardinality" value="1"}{else}{assign var="hasCardinality" value="0"}{/if}
{assign var=column value=$table->getAttributeColumn($attrId)}
{if $column->isWritable(1)}
{if $attr neq $primaryKey->_name}
      
      if ($record->isDirty('{$attr}')) {ldelim}
{/if}
{if $attribute->_cardinality}
        $attr ={if $attribute->_useReference}&{/if} $record->getAddedVals('{$attr}');
{else}
        $attr ={if $attribute->_useReference}&{/if} $record->getAttribute('{$attr}');
{/if}
{if $attribute->_isFile}
{if $attribute->_cardinality}
        $indexes = array_keys($attr);
        foreach($indexes as $index) {ldelim}
{/if}
        $attr{if $attribute->_cardinality}[$index]{/if}->_setEntityId($record->getPrimaryKey());
        
{if $attribute->_fileUriAttr && $entity->hasAttribute($attribute->_fileUriAttr)}
        // set file uris to the {$attribute->_fileUriAttr} attribute
{if $attribute->_cardinality}
        if (is_array(${$attribute->_name})) {ldelim}
          $keys = array_keys(${$attribute->_name});
          foreach($keys as $key) {ldelim}
            $uris = array();
{/if}
        if (SRA_FileAttribute::isValid(${$attribute->_name}{if $attribute->_cardinality}[$key]{/if})) {ldelim}
{if $attribute->_cardinality}
          $uris[] = ${$attribute->_name}[$key]->getUri()
{else}
          $record->setAttribute('{$attribute->_fileUriAttr}', ${$attribute->_name}->getUri());
{/if}
        {rdelim}
{if $attribute->_cardinality}
            $record->setAttribute('{$attribute->_fileUriAttr}', $uris);
          {rdelim}
        {rdelim}
{/if}
{/if} {* $attribute->_fileUriAttr && $entity->hasAttribute($attribute->_fileUriAttr) *}

{if $attribute->_cardinality}
        {rdelim}
{/if}
{/if} {* if $attribute->_isFile *}
{if $attribute->isEntity()}
        // check for any new records
{if $attribute->_cardinality}
        $indexes = array_keys($attr);
        foreach ($indexes as $index) {ldelim}
{/if}
        if ($attr && !$attr{if $attribute->_cardinality}[$index]{/if}->recordExists) {ldelim}
          if (SRA_Error::isError($attr{if $attribute->_cardinality}[$index]{/if}->insert())) {ldelim}
            if ($completeTransaction) {ldelim} $this->_db->rollback(); {rdelim}
            {include file="entity-aspect-after.tpl"}
            $msg = "{$className}::insert: Failed - Unable to insert relational attribute {$attr}";
            return SRA_Error::logError($msg, __FILE__, __LINE__);
          {rdelim}
{if $attribute->_cardinality && $attribute->isEntity()}
          else {ldelim}
            $obj = $attr[$index];
            unset($attr[$index]);
            $attr[$obj->getPrimaryKey()] = $obj;
          {rdelim}
{/if}
        {rdelim}
{if $attribute->_cardinality}
        {rdelim}
{/if}
{/if} {* if $attribute->isEntity() *}

{assign var="useBaseInsert" value="1"}
{if $attribute->isEntity()}
{assign var=foreignEntity value=$entity->getEntityGenerator($attribute->_type)}
{* stored in foreign entity table *}
{if ($foreignEntity->_name neq $entity->_name || ($foreignEntity->_name eq $entity->_name && $attribute->_cardinality)) && $foreignEntity->_table eq $table->getName()}
{assign var="useBaseInsert" value="0"}
{if $attribute->_cardinality}
        $indexes = array_keys($attr);
        foreach ($indexes as $index) {ldelim}
          $attrValue = {if $attribute->isEntity()}$attr[$index]->getPrimaryKey(){else}$attr[$index]{/if};
{/if}
{if $column->getReadConstraints($attr)}
{foreach from=$column->getReadConstraints($attr, 1) key=col item=val}
          $attr{if $attribute->_cardinality}[$index]{/if}->setColumnValue('{$col}', "{$val}");
{/foreach}
{/if}
          $stored = $attr{if $attribute->_cardinality}[$index]{/if}->setColumnValue('{$column->getName()}', $record);
          $dao =& SRA_DaoFactory::getDao('{$foreignEntity->_name}');
          if ($stored) {ldelim}
            if (SRA_Error::isError($dao->update($attr{if $attribute->_cardinality}[$index]{/if}))) {ldelim}
              if ($completeTransaction) {ldelim} $this->_db->rollback(); {rdelim}
              {include file="entity-aspect-after.tpl"}
              $msg = "{$className}::insert: Failed - Could not insert or update attribute {$attribute->_name}";
              return SRA_Error::logError($msg, __FILE__, __LINE__);
            {rdelim}
          {rdelim}
          else {ldelim}
            $sql = 'UPDATE {$foreignEntity->_table} SET {$column->getName()} = ' . $record->getAttrDbValue() . ' WHERE ' . $dao->getPkColumn() . ' = ' . $attr{if $attribute->_cardinality}[$index]{/if}->getAttrDbValue();
            if (SRA_Error::isError($results =& $this->_db->execute($sql))) {ldelim}
              if ($completeTransaction) {ldelim} $this->_db->rollback(); {rdelim}
              {include file="entity-aspect-after.tpl"}
              $msg = "{$className}::insert: Failed - SRA_Database query '${ldelim}sql{rdelim}' resulted in an SRA_Error";
              return SRA_Error::logError($msg, __FILE__, __LINE__);
            {rdelim}
          {rdelim}
{if $attribute->_cardinality}
        {rdelim}
{/if}
{/if} {* $foreignEntity->_table eq $table->getName() *}
{/if} {* $attribute->isEntity() *}

{* foreign table *}
{if $useBaseInsert}
{if !$renderBaseQuery}
{assign var=renderBaseQuery value="1"}
        $baseSql =  'INSERT INTO {$table->getName()} ';
        $started = FALSE;
        $nonPkAdded = FALSE;
        $colConstraint = '';
        $valConstraint = '';
        $colConstraints = array();
        $valConstraints = array();
{/if}
{if $attribute->_cardinality}
        if (!is_array($attr)) {ldelim}
          $attr = array();
        {rdelim}
        $indexes = array_keys($attr);
        $started = FALSE;
        foreach ($indexes as $index) {ldelim}
{/if}
{if !$attribute->_cardinality}
          $colConstraint .= $started ? ', ' : '';
          $valConstraint .= $started ? ', ' : '';
{/if}
          $colConstraint{if $attribute->_cardinality}s[] {else} .{/if}= '{$column->getName()}';
          $valConstraint{if $attribute->_cardinality}s[] {else} .{/if}= {if $column->getSetFunction()}'{$column->getSetFunction()}(' . {/if}$record->getAttrDbValue('{$attrId}'{if $attribute->_cardinality}, $attr[$index]{/if}){if $column->getSetFunction()} . ')'{/if};
          $started = TRUE;
{if $attr neq $primaryKey->_name}
          $nonPkAdded = TRUE;
{/if}
{if $attribute->_cardinality}

        {rdelim}
{/if}
{/if}        {* $useBaseInsert *}
{if $attr neq $primaryKey->_name}

      {rdelim}
{/if}
{* get select constraint values *}
{if !$readConstraints}{assign var=$readConstraints value=$column->getReadConstraints($attr, 1)}{/if}
{/if}        {* $column->isWritable(1) *}
{/if}        {* !$entity->isPrimaryTableAttr($attr) *}
{/foreach}   {* $attrs *}

{if $renderBaseQuery}
      // execute insert query
      if ($nonPkAdded) {ldelim}
{if $readConstraints}
{* add readConstraints as defined in em "constraint" value for this attribute *}
{foreach from=$readConstraints key=col item=val}
        $colConstraint .= $started ? ', ' : '';
        $valConstraint .= $started ? ', ' : '';
        $colConstraint .= '{$col}';
        $valConstraint .= "{$val}";
{/foreach}
{/if}
{if $hasCardinality}
        if (count($colConstraints)) {ldelim}
          $keys = array_keys($colConstraints);
          foreach ($keys as $key) {ldelim}
            $sql = $baseSql . '(' . $colConstraint;
            $sql .= $colConstraint ? ', ' : '';
            $sql .= $colConstraints[$key];
            $sql .= ') VALUES (' . $valConstraint;
            $sql .= $valConstraint ? ', ' : '';
            $sql .= $valConstraints[$key];
            $sql .= ')';
            if (SRA_Error::isError($results =& $this->_db->execute($sql))) {ldelim}
              {include file="entity-aspect-after.tpl"}
              if ($completeTransaction) {ldelim} $this->_db->rollback(); {rdelim}
              $msg = "{$className}::insert: Failed - SRA_Database query '${ldelim}sql{rdelim}' resulted in an SRA_Error";
              return SRA_Error::logError($msg, __FILE__, __LINE__);
            {rdelim}
          {rdelim}
        {rdelim}
        else {ldelim}
{/if}
          $sql = $baseSql . '(' . $colConstraint . ') VALUES (' . $valConstraint . ')';
          if (SRA_Error::isError($results =& $this->_db->execute($sql))) {ldelim}
            {include file="entity-aspect-after.tpl"}
            if ($completeTransaction) {ldelim} $this->_db->rollback(); {rdelim}
            $msg = "{$className}::insert: Failed - SRA_Database query '${ldelim}sql{rdelim}' resulted in an SRA_Error";
            return SRA_Error::logError($msg, __FILE__, __LINE__);
          {rdelim}
{if $hasCardinality}
        {rdelim}
{/if}
      {rdelim}{* if ($nonPkAdded) *}
{/if}        {* if $renderBaseQuery *}

    {rdelim}{* if ($record->isDirty($attr)) *}


{/foreach}      {* $table->getAttrGroups() *}
{/foreach}      {* $schema->getTables() *}
    
    // commit transaction updates
    if ($completeTransaction) {ldelim} $this->_db->commit(); {rdelim}
    
    $oldDirtyFlags = $record->_dirty;
    $inserted = TRUE;
    $record->resetDirtyFlags({if $entity->_fileHandling eq $smarty.const.SRA_FILE_ATTRIBUTE_TYPE_DB}array({foreach from=$entity->getAttributes() item=attribute}{if $attribute->_isFile && !$attribute->_cardinality}'{$attribute->_name}', {/if}{/foreach}){/if});
    
{if $entity->_fileHandling eq $smarty.const.SRA_FILE_ATTRIBUTE_TYPE_DB}
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_isFile && !$attribute->_cardinality}
    if ($record->isDirty('{$attribute->_name}') && SRA_FileAttribute::isValid($record->getAttribute('{$attribute->_name}'))) {ldelim}
        $record->_{$attribute->_name}->_setEntityId($record->getPrimaryKey());
{if $attribute->_fileUriAttr && $entity->hasAttribute($attribute->_fileUriAttr)}
        // set file uri to the {$attribute->_fileUriAttr} attribute
        $record->setAttribute('{$attribute->_fileUriAttr}', $record->_{$attribute->_name}->getUri());
{/if} {* $attribute->_fileUriAttr && $entity->hasAttribute($attribute->_fileUriAttr) *}
    {rdelim}
{/if}
{/foreach}
    if ($record->isDirty()) {ldelim} $this->update($record); {rdelim}
{/if}
    
    if ($insertSubEntities) {ldelim}
      $this->updateSubEntities($record);
    {rdelim}

    {include file="entity-aspect-after.tpl"}
    return $inserted;
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} newInstance
  /**
   * returns a new instance of a {$entity->_name}{$entity->_voSuffix} object
   * 
   * @param array $params any initialization params (optional)
   * @access  public
   * @return void
   */
  function &newInstance($params=NULL) {ldelim}
    {$Template->assign('aopMethodName', "newInstance")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    return new {$entity->_name}{$entity->_voSuffix}($params);
  {rdelim}
  // {rdelim}{rdelim}{rdelim}

  
  // {ldelim}{ldelim}{ldelim} update
  /**
   * This method is used to update an existing {$entity->_name} object in the 
   * persistency store managed by this DAO. . If the $record does not exist, the 
   * insert method will be invoked instead. returns TRUE if an update was 
   * necessary and performed. FALSE if an update was not necessary because the 
   * $record was not dirty
   * @param {$voClassName} $record The {$entity->_name} instance to update.
   * @param boolean $updateSubEntities whether or not sub-entities should also 
   * be checked and updated (only if they have been loaded)
   * @access  public
   * @return boolean
   */
  function update(& $record, $updateSubEntities = FALSE) {ldelim}
    {$Template->assign('aopMethodName', "update")}
    {include file="entity-aspect-before.tpl"}
    // check if param is a valid {$voClassName} instance
    if (!{$voClassName}::isValid($record)) {ldelim}
      $msg = "{$className}::update: Failed - parameter is not a valid {$voClassName} instance";
      {include file="entity-aspect-after.tpl"}
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    
    // does record not exist? if it does not, pass to the insert method
    if (!$record->recordExists) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return $this->insert($record, $updateSubEntities);    
    {rdelim}
    
    // validate {$voClassName}
    if (!$record->validate()) {ldelim}
      {include file="entity-aspect-after.tpl"}
      $msg = "{$className}::update: Failed - {$voClassName} instance validation failed: " . implode(', ', $record->validateErrors);
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    
    // validate primary key - must be set
    if (!$record->getPrimaryKey()) {ldelim}
      {include file="entity-aspect-after.tpl"}
      $msg = "{$className}::update: Failed - No primary key specified for this {$voClassName}";
      return SRA_Error::logError($msg, __FILE__, __LINE__);
    {rdelim}
    
    // don't update if not dirty
    if ($updateSubEntities && !$record->isDirty()) {ldelim}
      $this->updateSubEntities($record);
      {include file="entity-aspect-after.tpl"}
      return FALSE;
    {rdelim}
    
    // start transaction
    $completeTransaction = TRUE;
    if (!$this->_db->isInTransaction()) {ldelim}
      $this->_db->startTransaction();
    {rdelim}
    else {ldelim}
      $completeTransaction = FALSE;
    {rdelim}
    
{foreach from=$schema->getTables() item=table}
{foreach from=$table->getAttributeGroups() item=attrs}
{assign var="hasCardinality" value="0"}

    if ($record->isDirty(array({foreach from=$attrs key=attrId item=attr}{assign var=attribute value=$entity->getAttributes($attr)}{if $attr neq $primaryKey->_name}'{if $attribute->getMappedAttributes()}{$attrId}{else}{$attr}{/if}', {/if}{/foreach}))) {ldelim}
{assign var=renderBaseQuery value="0"}
{assign var=readConstraints value="0"}
{foreach from=$attrs key=attrId item=attr}
{assign var=attribute value=$entity->getAttributes($attr)}
{if $attribute->_tablePkColumn}{assign var=pkColName value=$attribute->_tablePkColumn}{else}{assign var=pkColName value=$primaryKey->_column}{/if}
{assign var=foreignEntity value="0"}
{if $attribute->isEntity()}{assign var=foreignEntity value=$entity->getEntityGenerator($attribute->_type)}{/if}
{assign var=column value=$table->getAttributeColumn($attrId)}
{if !$readConstraints}{assign var=$readConstraints value=$column->getReadConstraints($attr, 1)}{/if}
{if $attr neq $primaryKey->_name}

      if ($record->isDirty('{if $attribute->getMappedAttributes()}{$attrId}{else}{$attr}{/if}')) {ldelim}
{/if}
{if $attribute->_cardinality && !$attribute->_aggregateCardinality}
{assign var="hasCardinality" value="1"}
        // removed values
        $removed =& $record->getRemovedVals('{$attr}');
        $keys = array_keys($removed);
        foreach ($keys as $key) {ldelim}
{if $attribute->isEntity()}
          // skip, if this record has already been deleted
          if (!$removed[$key]->recordExists || isset($removedRecords['{$table->getName()}_' . $record->getPrimaryKey() . '_' . $removed[$key]->getPrimaryKey()])) {ldelim}
            continue;
          {rdelim}
{/if}
{assign var=addSqlCode value=0}
{if !$attribute->isEntity() || ($attribute->isEntity() && $table->getName() neq $foreignEntity->_table)}
{assign var=addSqlCode value=1}
          $sql = 'DELETE FROM {$table->getName()} WHERE {$pkColName} = ' . $record->getAttrDbValue() . ' AND {if $attribute->isEntity()}' . $removed[$key]->getPrimaryKeyColumn() . '{else}{$column->getName()}{/if} = ' . {if $attribute->isEntity()}$removed[$key]->getAttrDbValue(){else}$record->getAttrDbValue('{$attr}', $removed[$key]){/if};
{elseif !$attribute->isEntity() || ($attribute->isEntity() && !$attribute->_onRemoveDelete)}
{assign var=addSqlCode value=1}
          $sql = 'UPDATE {$table->getName()} SET {$pkColName} = {if $attribute->_nullDbEmptyStr}\'\'{else}NULL{/if} WHERE {$pkColName} = ' . $record->getAttrDbValue() . ' AND {if $attribute->isEntity()}' . $removed[$key]->getPrimaryKeyColumn() . '{else}{$column->getName()}{/if} = ' . {if $attribute->isEntity()}$removed[$key]->getAttrDbValue(){else}$record->getAttrDbValue('{$attr}', $removed[$key]){/if};
{/if}
{if $addSqlCode}
{if $column->getReadConstraints($attr)}
{foreach from=$column->getReadConstraints($attr, 1) key=col item=val}
          $sql .= " AND {$col} = {$val}";
{/foreach}
{/if}
          if (SRA_Error::isError($results =& $this->_db->execute($sql))) {ldelim}
            if ($completeTransaction) {ldelim} $this->_db->rollback(); {rdelim}
            {include file="entity-aspect-after.tpl"}
            $msg = "{$className}::update: Failed - SRA_Database query '${ldelim}sql{rdelim}' resulted in an SRA_Error";
            return SRA_Error::logError($msg, __FILE__, __LINE__);
          {rdelim}
{/if} {* if $addSqlCode *}
          
{if $attribute->isEntity()}
          $removedRecords['{$table->getName()}_' . $record->getPrimaryKey() . '_' . $removed[$key]{if $attribute->isEntity()}->getPrimaryKey(){/if}] = TRUE;
{/if}
          
{if $attribute->_onRemoveDelete && $attribute->isEntity()}
          $dao =& SRA_DaoFactory::getDao('{$attribute->_type}');
          if (SRA_Error::isError($dao->delete($removed[$key]))) {ldelim}
            if ($completeTransaction) {ldelim} $this->_db->rollback(); {rdelim}
            {include file="entity-aspect-after.tpl"}
            $msg = '{$className}::update: Failed - Unable to remove attribute {$attribute->_name}';
            return SRA_Error::logError($msg, __FILE__, __LINE__);
          {rdelim}
{/if}
        {rdelim}
        
        $attrVals = array();
        $added =& $record->getAddedVals('{$attr}');
{if $attribute->isEntity()}
        // check if any are new
        $akeys = array_keys($added);
        foreach ($akeys as $akey) {ldelim}
          if (!$added[$akey]->recordExists) {ldelim}
            $added[$akey]->insert();
          {rdelim}
        {rdelim}
{/if}
        $changed =& $record->getChangedVals('{$attr}');
        $attr = array();
        $counter = 0;
        $keys = array_keys($added);
        foreach($keys as $key) {ldelim}
          $attrVals[$counter] ={if $attribute->_useReference}&{/if} $added[$key];
          $attr[$counter++] =& $added[$key];
        {rdelim}
        $changedStart = $counter;
        $keys = array_keys($changed);
        foreach($keys as $key) {ldelim}
          $attrVals[$counter] ={if $attribute->_useReference}&{/if} $changed[$key];
          $attr[$counter++] =& $changed[$key];
        {rdelim}
        $indexes = array_keys($attr);
        foreach ($indexes as $index) {ldelim}
          $isAdded = $index < $changedStart;
{else}
{assign var="hasCardinality" value="0"}
        $attr ={if $attribute->_useReference}&{/if} $record->getAttribute('{$attr}');

{/if} {* $attribute->_cardinality *}

{assign var="useBaseInsert" value="1"}
{if $attribute->isEntity()}
{* stored in foreign entity table *}
{if $foreignEntity->_table eq $table->getName() && $attribute->_cardinality}
{assign var="useBaseInsert" value="0"}
{if $column->getReadConstraints($attr)}
{foreach from=$column->getReadConstraints($attr, 1) key=col item=val}
        $attr->setColumnValue('{$col}', "{$val}");
{/foreach}
{/if}
        $stored = $attr{if $attribute->_cardinality}[$index]{/if}->setColumnValue('{$column->getName()}', $record);
        $dao =& SRA_DaoFactory::getDao('{$foreignEntity->_name}');
        if ($stored) {ldelim}
          if (SRA_Error::isError($dao->update($attr{if $attribute->_cardinality}[$index]{/if}))) {ldelim}
            if ($completeTransaction) {ldelim} $this->_db->rollback(); {rdelim}
            {include file="entity-aspect-after.tpl"}
            $msg = "{$className}::insert: Failed - Could not insert or update attribute {$attribute->_name}";
            return SRA_Error::logError($msg, __FILE__, __LINE__);
          {rdelim}
        {rdelim}
        else {ldelim}
          $sql = 'UPDATE {$foreignEntity->_table} SET {$column->getName()} = ' . $record->getAttrDbValue() . ' WHERE ' . $dao->getPkColumn() . ' = ' . $attr{if $attribute->_cardinality}[$index]{/if}->getAttrDbValue();
          if (SRA_Error::isError($results =& $this->_db->execute($sql))) {ldelim}
            if ($completeTransaction) {ldelim} $this->_db->rollback(); {rdelim}
            {include file="entity-aspect-after.tpl"}
            $msg = "{$className}::insert: Failed - SRA_Database query '${ldelim}sql{rdelim}' resulted in an SRA_Error";
            return SRA_Error::logError($msg, __FILE__, __LINE__);
          {rdelim}
        {rdelim}
{/if}     {* $foreignEntity->_table eq $table->getName() *}
{/if}     {* $attribute->isEntity() *}

{* primary key, add to where clause only *}
{if $useBaseInsert && !$renderBaseQuery}
{assign var=renderBaseQuery value="1"}
        $colConstraints = array();
        $valConstraints = array();
        $whereCols = array();
        $whereVals = array();
        $addedVals = array();
        $whereCol = '';
        $whereVal = '';
        $removedRecords = array();
{/if}
{if $useBaseInsert && $attr eq $primaryKey->_name}
        $whereCol = '{$column->getName()}';
        $whereVal = $record->getAttrDbValue();
{* non-primary key, add to set clause *}
{elseif $useBaseInsert}
{if $attribute->_cardinality && !$attribute->_aggregateCardinality}
        if (!isset($colConstraints[$index])) {ldelim}
          $colConstraints[$index] = array();
          $valConstraints[$index] = array();
        {rdelim}
        $whereCols[$index] = '{$column->getName()}';
        $whereVals[$index] = $record->getAttrDbValue('{$attrId}', {if $attribute->_cardinality && !$attribute->_aggregateCardinality}$attrVals[$index]{else}FALSE{/if}, TRUE);
        $addedVals[$index] = $isAdded;
{/if}
        $colConstraints{if $attribute->_cardinality && !$attribute->_aggregateCardinality}[$index]{/if}[] = '{$column->getName()}';
        $valConstraints{if $attribute->_cardinality && !$attribute->_aggregateCardinality}[$index]{/if}[] = {if $column->getSetFunction()}'{$column->getSetFunction()}(' . {/if}$record->getAttrDbValue('{$attrId}'{if $attribute->_cardinality && !$attribute->_aggregateCardinality}, $attrVals[$index]{/if}){if $column->getSetFunction()} . ')'{/if};
{/if}     {* $attr eq $primaryKey->_name *}
{if $attribute->_cardinality && !$attribute->_aggregateCardinality}

        {rdelim}
{/if}
{if $attr neq $primaryKey->_name}

      {rdelim}{* if ($record->isDirty($attr)) *}
{/if}     {* $attr eq $primaryKey->_name *}
{/foreach}{* from=$attrs key=attrId item=attr *}

{* create update/insert queries *}
{if $renderBaseQuery}

        if (count($colConstraints) && $whereCol) {ldelim}
{if $readConstraints}
{foreach from=$readConstraints key=col item=val}
{if $hasCardinality}
          $keys = array_keys($colConstraints);
          foreach ($keys as $key) {ldelim}
{/if}
          $colConstraints{if $hasCardinality}[$key]{/if}[] .= '{$col}';
          $valConstraints{if $hasCardinality}[$key]{/if}[] .= "{$val}";
{if $hasCardinality}
          {rdelim}
{/if}
{/foreach}
{/if}
{if $hasCardinality}
          $ckeys = array_keys($colConstraints);
          foreach ($ckeys as $ckey) {ldelim}
          $results = FALSE;
          if (!$addedVals[$ckey]) {ldelim}
{/if}
{if !$hasCardinality && $attribute->isEntity() && $attribute->_onRemoveDelete}
          if ($removed =& $record->getRemovedVals('{$attribute->_name}')) {ldelim}
            $dao =& SRA_DaoFactory::getDao('{$attribute->_type}');
            $keys = array_keys($removed);
            foreach ($keys as $key) {ldelim}
              $removePk = $removed[$key]->getPrimaryKey();
              if (SRA_Error::isError($dao->delete($removed[$key]))) {ldelim}
                if ($completeTransaction) {ldelim} $this->_db->rollback(); {rdelim}
                {include file="entity-aspect-after.tpl"}
                $msg = '{$className}::update: Failed - Unable to remove attribute {$attribute->_name}';
                return SRA_Error::logError($msg, __FILE__, __LINE__);
              {rdelim}
{if $table->getName() neq $primaryTable->getName()}
              $sql = 'DELETE FROM {$table->getName()} WHERE ' . $whereCol . '=' . $whereVal . ' AND ' . $colConstraints[0] . '=' . $removePk;
              if (SRA_Error::isError($results =& $this->_db->execute($sql))) {ldelim}
                if ($completeTransaction) {ldelim} $this->_db->rollback(); {rdelim}
                {include file="entity-aspect-after.tpl"}
                $msg = "{$className}::update: Failed - SRA_Database query '${ldelim}sql{rdelim}' resulted in an SRA_Error";
                return SRA_Error::logError($msg, __FILE__, __LINE__);
              {rdelim}
{/if}
            {rdelim}
          {rdelim}
{/if}
          // first try an update
          $sql = 'UPDATE {$table->getName()} SET ';
          $existsSql = 'SELECT count(*) FROM {$table->getName()}';
          $started = FALSE;
          $keys = array_keys($colConstraints{if $hasCardinality}[$ckey]{/if});
          foreach ($keys as $key) {ldelim}
            $sql .= $started ? ', ' : '';
            $sql .= $colConstraints{if $hasCardinality}[$ckey]{/if}[$key] . ' = ' . $valConstraints{if $hasCardinality}[$ckey]{/if}[$key];
            $started = TRUE;
          {rdelim}
          $sql .= ' WHERE ' . $whereCol . ' = ' . $whereVal;
          $existsSql .= ' WHERE ' . $whereCol . ' = ' . $whereVal;
{if $attribute->_cardinality}
          if ($whereCols[$ckey]) {ldelim}
            $sql .= ' AND ' . $whereCols[$ckey] . ' = ' . $whereVals[$ckey];
            $existsSql .= ' AND ' . $whereCols[$ckey] . ' = ' . $whereVals[$ckey];
          {rdelim}
{/if}
          if (SRA_Error::isError($results =& $this->_db->execute($sql))) {ldelim}
            if ($completeTransaction) {ldelim} $this->_db->rollback(); {rdelim}
            {include file="entity-aspect-after.tpl"}
            $msg = "{$className}::update: Failed - SRA_Database query '${ldelim}sql{rdelim}' resulted in an SRA_Error";
            return SRA_Error::logError($msg, __FILE__, __LINE__);
          {rdelim}
{if $hasCardinality}
          {rdelim}
{/if}
{if $table->getName() neq $primaryTable->getName()}
          // no rows were affected by update query so a new record is needed
          if ({if $hasCardinality}!$results || {elseif $attribute->isEntity()}$attr !== NULL && {/if}!SRA_Database::getQueryValue($this->_db, $existsSql, SRA_DATA_TYPE_INT)) {ldelim}
            $sql = 'INSERT INTO {$table->getName()} (' . $whereCol;
            $keys = array_keys($colConstraints{if $hasCardinality}[$ckey]{/if});
            foreach ($keys as $key) {ldelim}
              $sql .= ', ' . $colConstraints{if $hasCardinality}[$ckey]{/if}[$key];
            {rdelim}
            $sql .= ') VALUES (' . $whereVal;
            $keys = array_keys($valConstraints{if $hasCardinality}[$ckey]{/if});
            foreach ($keys as $key) {ldelim}
              $sql .= ', ' . $valConstraints{if $hasCardinality}[$ckey]{/if}[$key];
            {rdelim}
            $sql .= ')';
            if (SRA_Error::isError($results =& $this->_db->execute($sql))) {ldelim}
              if ($completeTransaction) {ldelim} $this->_db->rollback(); {rdelim}
              {include file="entity-aspect-after.tpl"}
              $msg = "{$className}::update: Failed - SRA_Database query '${ldelim}sql{rdelim}' resulted in an SRA_Error";
              return SRA_Error::logError($msg, __FILE__, __LINE__);
            {rdelim}
          {rdelim}
{/if}  {* $table->getName() eq $primaryTable->getName() *}

{if $hasCardinality}
          {rdelim}
{/if}

      {rdelim}{* if (!count($colConstraints) && $whereCol) *}
{/if} {* $useBaseInsert *}

    {rdelim}{* if ($record->isDirty($attr...)) *}

{/foreach}      {* $table->getAttrGroups() *}
{/foreach}      {* $schema->getTables() *}
    
    // commit transaction updates
    if ($completeTransaction) {ldelim} $this->_db->commit(); {rdelim}
    
    $oldDirtyFlags = $record->_dirty;
    $updated = TRUE;
    $record->resetDirtyFlags();
    if ($updateSubEntities) {ldelim}
      $this->updateSubEntities($record);
    {rdelim}
    
    {include file="entity-aspect-after.tpl"}
    return $updated;
    
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} reload
  /**
   * reloads the given {$entity->_name} object with the current data for that 
   * object in the database
   * @param ${$entity->_name} the object to reload. must exist in the database
   * @access  public
   * @return {$entity->_name}{$entity->_voSuffix}
   */
  function &reload(& ${$entity->_name}) {ldelim}
    {$Template->assign('aopMethodName', "reload")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    return $this->findByPk(${$entity->_name}->getPrimaryKey(), TRUE);
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} updateSubEntities
  /**
   * this method updates any dirty, previous loaded sub-entities in $record
   * @param $record the object to update the sub entities for
   * @access  public
   * @return void
   */
  function updateSubEntities(& $record) {ldelim}
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->isEntity() && !$attribute->getMappedAttributes() && !$attribute->_skipPersistence}
    if (isset($record->_{$attribute->_name})) {ldelim}
{if $attribute->_cardinality}
      $keys = array_keys($record->_{$attribute->_name});
      foreach ($keys as $key) {ldelim}
{/if}
        if ({$attribute->_type}{$entity->_voSuffix}::isValid($record->_{$attribute->_name}{if $attribute->_cardinality}[$key]{/if}) && $record->_{$attribute->_name}{if $attribute->_cardinality}[$key]{/if}->isDirty()) {ldelim}
          if (!$record->_{$attribute->_name}{if $attribute->_cardinality}[$key]{/if}->recordExists) {ldelim}
            if (!SRA_Error::isError($record->_{$attribute->_name}{if $attribute->_cardinality}[$key]{/if}->insert(TRUE))) {ldelim}
{if !$attribute->_cardinality && !$attribute->_table && !$attribute->_tablePkColumn}
              // attribute primary key stored in {$entity->_name} table
              $this->_db->execute('UPDATE {$entity->_table} SET {$attribute->_column}=' . $record->_{$attribute->_name}->getPrimaryKey() . ' WHERE {$primaryKey->_column}=' . $record->getPrimaryKey());
{elseif !$attribute->_table && ($attribute->_cardinality || $attribute->_tablePkColumn)}
              // {$entity->_name} primary key stored in foreign {$attribute->_type} table
              $this->_db->execute('UPDATE {$attribute->getEntityTable()} SET {if $attribute->_tablePkColumn}{$attribute->_tablePkColumn}{else}{$primaryKey->_column}{/if}=' . $record->getPrimaryKey() . ' WHERE {$attribute->getEntityPkColumn()}=' . $record->_{$attribute->_name}{if $attribute->_cardinality}[$key]{/if}->getPrimaryKey());
{elseif $attribute->_table}
              // primary keys of both stored in link table
              if (!SRA_Database::getQueryValue($this->_db, 'SELECT count(*) FROM {$attribute->_table} WHERE {if $attribute->_tablePkColumn}{$attribute->_tablePkColumn}{else}{$primaryKey->_column}{/if}=' . $record->getPrimaryKey() . ' AND {$attribute->getEntityPkColumn()}=' . $record->_{$attribute->_name}{if $attribute->_cardinality}[$key]{/if}->getPrimaryKey())) {ldelim}
                $this->_db->execute('INSERT INTO {$attribute->_table} ({if $attribute->_tablePkColumn}{$attribute->_tablePkColumn}{else}{$primaryKey->_column}{/if}, {$attribute->getEntityPkColumn()}) VALUES (' . $record->getPrimaryKey() . ', ' . $record->_{$attribute->_name}{if $attribute->_cardinality}[$key]{/if}->getPrimaryKey() . ')');
              {rdelim}
{/if}
            {rdelim}
          {rdelim}
          else {ldelim}
            $record->_{$attribute->_name}{if $attribute->_cardinality}[$key]{/if}->update(TRUE);
          {rdelim}
        {rdelim}
{if $attribute->_cardinality}
      {rdelim}
{/if}
    {rdelim}
{/if}
{/foreach}
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // {ldelim}{ldelim}{ldelim} toString
  /**
   * Returns a string representation of this object
   * @access  public
   * @return String
   */
  function toString() {ldelim}
    {$Template->assign('aopMethodName', "toString")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    return SRA_Util::objectToString($this);
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
  
  // private operations
  
  
  // public static methods
  
  // {ldelim}{ldelim}{ldelim} isValid()
  /**
   * Static method that returns true if the object parameter is a {$className} object.
   *
   * @param  Object $object The object to validate
   * @access  public
   * @return  boolean
   */
  function isValid( & $object ) {ldelim}
    {$Template->assign('aopMethodName', "isValid")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    return (is_object($object) && (!isset($object->err) || !SRA_Error::isError($object->err)) && strtolower(get_class($object)) == '{$className|lower}' || is_subclass_of($object, '{$className|lower}'));
  {rdelim}
  // {rdelim}{rdelim}{rdelim}

  
  // aop methods
{foreach from=$entity->getAopIntroductions($smarty.const.SRA_AOP_INTRODUCTION_TYPE_METHOD, $aopClassType) item=introduction}
  // {ldelim}{ldelim}{ldelim} {$introduction->getValue()}
  function {$introduction->getValue()} {ldelim}
    {$introduction->getCode()}
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
{/foreach}

  
{rdelim}
// {rdelim}{rdelim}{rdelim}
?>
Return current item: Sierra-php PHP Application Framework