Location: PHPKode > projects > Sierra-php PHP Application Framework > sierra/lib/model/vo.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_VO)}
// {ldelim}{ldelim}{ldelim} Imports
{if $entity->_voExtendsFile}
require_once('{$entity->_voExtendsFile}');
{/if}
// {rdelim}{rdelim}{rdelim}

// {ldelim}{ldelim}{ldelim} Constants

/**
 * key to use in the associative _dirty array to identify attributes that have 
 * been added
 */
if (!defined('SRA_ATTRIBUTE_ADD_DIRTY_KEY')) {ldelim}
define('SRA_ATTRIBUTE_ADD_DIRTY_KEY', '#ADD#');
{rdelim}

/**
 * key to use in the associative _dirty array to identify attributes that have 
 * been removed
 */
if (!defined('SRA_ATTRIBUTE_REMOVE_DIRTY_KEY')) {ldelim}
define('SRA_ATTRIBUTE_REMOVE_DIRTY_KEY', '#REMOVE#');
{rdelim}

/**
 * used to identify GET forms
 * @see {$className}#newInstanceFromForm
 */
if (!defined('SRA_ENTITY_VO_GET_FORM')) {ldelim}
define('SRA_ENTITY_VO_GET_FORM', 'get');
{rdelim}

/**
 * used to identify POST forms
 * @see {$className}#newInstanceFromForm
 */
if (!defined('SRA_ENTITY_VO_POST_FORM')) {ldelim}
define('SRA_ENTITY_VO_POST_FORM', 'post');
{rdelim}

/**
 * used to identify that an entity attribute was not loaded because when loading 
 * was attempted, it was already in the process of loading that entity instance
 * this usually only occurs when circular references exist between entities 
 * 
 */
if (!defined('SRA_ENTITY_ATTRIBUTE_CIRC_REF')) {ldelim}
define('SRA_ENTITY_ATTRIBUTE_CIRC_REF', -1);
{rdelim}

  // 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 Value Object (VO) 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->_voExtends} extends {$entity->_voExtends}{/if} {ldelim}
  // {ldelim}{ldelim}{ldelim} Attributes
  // public attributes
	/**
	 * stores error messages set due to a validation errors
	 * @type string
	 * @access public
	 */
	var $validateErrors = array();
	
	/**
	 * package variable identifying whether or not this object exists in the 
	 * persistency store
	 * @type boolean
	 * @access package
	 */
	var $recordExists = FALSE;
	
  
  // private attributes
	/**
	 * array used to keep track of the original values that were set for dirty 
   * attributes. 
	 * @type array
	 * @access private
	 */
	var $_clean = array();
  
	/**
	 * array used to keep track of which entity attributes are dirty. attributes 
	 * become dirty if a corresponding set/add/remove method is called for that 
	 * attribute
	 * @type array
	 * @access private
	 */
	var $_dirty = array();
	
	/**
	 * used to keep track of which lazy load attributes have been loaded
	 * @type array
	 * @access private
	 */
	var $_lazyLoaded = array();
	
	/**
	 * used to store primary keys of lazy-loadable instance attributes
	 * @type array
	 * @access private
	 */
	var $_lazyLoadPks = array();
  
  /**
   * used to keep track of linked (recursive or union) attributes that have been 
   * loaded
   * @type array
   * @access private
   */
  var $_linkedAttributes = array();
	
	/**
	 * used to keep track of the name of the attribute that is currently being 
	 * rendered
	 * @type string
	 * @access private
	 */
	var $_renderAttributeName;
  
  /**
   * flag used to keep track of whether or not the toXmlArray() method is 
   * currently processing. this is used to avoid recursive loops
   * @type boolean
   * @access private
   */
  var $_renderingXmlArray = FALSE;
	
	/**
	 * used to store whether or not a particular attribute has been "set" using 
	 * the corresponding "set" or "add" method
	 * @type array
	 * @access private
	 */
	var $_setAttrs = array();
	
{foreach from=$entity->getAttributes() item=attribute}
	/**
	 * {if $attribute->_apiResource}{$resources->getString($attribute->_apiResource)}{/if}

	 * 
	 * @type {$attribute->_type}
	 * @access private
	 */
	var $_{$attribute->_name}{if $attribute->_cardinality} = array(){/if};
	
{/foreach}

  // 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
	 * the following default values will be set when this object is instantiated 
	 * IF appendDirty is TRUE and $initVals does not already set these attributes:
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_default}
	 *		{$attribute->_name} => {$attribute->_default}
{/if}
{/foreach}
	 * @param mixed $initVals either the path to a file containing the 
   * serialization string for the object instance, the actual serialization 
   * string, or a hash of attribute/value pairs to use when instantiating this 
   * object (see the "setAttribute" method for information on how this parameter 
   * should be structured)
	 * @param boolean $appendDirty whether or not the _dirty attribute should be 
	 * appended to reflect values set from the $initVals parameter will be 
	 * considered _dirty changes. If TRUE, default values will also be set for 
	 * this entity
   * @param boolean $recordExists whether or not the instance of this object 
   * being instantiated already exists in the datastore
   * @access public
	 */
	function {$className}($initVals = FALSE, $appendDirty = TRUE, $recordExists = FALSE) {ldelim}
    {$Template->assign('aopMethodName', $className)}
    {include file="entity-aspect-before.tpl"}
    
    // unserialize
    if ($initVals && !is_array($initVals) && is_file($initVals)) {ldelim}
      $initVals =& SRA_File::toString($initVals);
    {rdelim}
    // convert xml
    if ($initVals && (is_string($initVals) || (is_array($initVals) && isset($initVals['{$entity->getDtdName()}'])))) {ldelim}
      if (is_string($initVals)) {ldelim}
        $parser = new SRA_XmlParser($initVals, TRUE);
        $data =& $parser->getData();
      {rdelim}
      else {ldelim}
        $data = $initVals;
      {rdelim}
      $initVals = array();
      $recordExists = $recordExists ? TRUE : isset($data['{$entity->getDtdName()}']['attributes']['recordexists']) && $data['{$entity->getDtdName()}']['attributes']['recordexists'] == '1';
{if $entity->getDtdAttributes()}
{foreach from=$entity->getDtdAttributes() item=attribute}
      if (isset($data['{$entity->getDtdName()}']['{$attribute->getDtdName()}'])) $initVals['{$attribute->_name}'] = $data['{$entity->getDtdName()}']['{$attribute->getDtdName()}'];
{/foreach}
{/if}
{foreach from=$entity->getDtdElements() item=attribute}
      if ($val = isset($data['{$entity->getDtdName()}']['{$attribute->getNestedElementDtdName()}']) ? $data['{$entity->getDtdName()}']['{$attribute->getNestedElementDtdName()}'] : (isset($data['{$entity->getDtdName()}'][0]['{$attribute->getNestedElementDtdName()}']) ? $data['{$entity->getDtdName()}'][0]['{$attribute->getNestedElementDtdName()}'] : NULL)) {ldelim}
{if $attribute->_cardinality}
        $aval = array();
        foreach(array_keys($val) as $key) {ldelim}
{if $attribute->isEntity()}
          if (isset($val[$key]['{$attribute->getTypeDtdName()}'][0])) {ldelim}
            foreach(array_keys($val[$key]['{$attribute->getTypeDtdName()}']) as $vkey) {ldelim}
              $aval[] = new {$attribute->_type}{$entity->_voSuffix}(array('{$attribute->getTypeDtdName()}' => $val[$key]['{$attribute->getTypeDtdName()}'][$vkey]), $appendDirty, $recordExists);
            {rdelim}
          {rdelim}
          else {ldelim}
{/if}
            $aval[] = {if $attribute->isEntity()}{if $entity->attrIsPersistent($attribute->_name)}$key{else}new {$attribute->_type}{$entity->_voSuffix}($val[$key], $appendDirty, $recordExists){/if}{else}$val[$key]['xml_value']{/if};
{if $attribute->isEntity()}
          {rdelim}
{/if}
        {rdelim}
        $initVals['{$attribute->_name}'] = $aval;
{else}
        $val = SRA_ArrayManager::getElement($val, 0);
        $initVals['{$attribute->_name}'] = {if $attribute->isEntity() && !$entity->attrIsPersistent($attribute->_name)}new {$attribute->_type}{$entity->_voSuffix}($val, $appendDirty, $recordExists){else}$val['xml_value']{/if};
{/if}
      {rdelim}
{/foreach}
    {rdelim}
    
    $this->recordExists = $recordExists;
{if $primaryKey && !$entity->_skipPersistence}
		if (is_array($initVals)) {ldelim}
			$keys = array_keys($initVals);
      // look for primary key
      if ($appendDirty) {ldelim}
        foreach ($keys as $key) {ldelim}
          if ($key == '{$primaryKey->_name}' && $initVals[$key]) {ldelim}
            $dao =& $this->getDao();
            if (method_exists($dao, 'findByPk')) {ldelim} $initObj =& $dao->findByPk($initVals[$key]); {rdelim}
            if ($this->isValid($initObj)) {ldelim}
              SRA_Util::mergeObject($this, $initObj);
              $this->recordExists = TRUE;
            {rdelim}
            break;
          {rdelim}
        {rdelim}
        
        if (isset($initVals['{$primaryKey->_name}'])) {ldelim}
          unset($initVals['{$primaryKey->_name}']);
        {rdelim}
        
        $keys = array_keys($initVals);
      {rdelim}
    {rdelim}
{/if}
    $this->setAttributes($initVals, $appendDirty);

{if $entity->_parentEntity}
    // call parent constructor
		parent::{$entity->_parentEntity}($initVals, $appendDirty);
{/if}
    $initKeys = is_array($initVals) ? array_keys($initVals) : array();
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_default !== $smarty.const.NULL}
    // set default value for {$attribute->_name}
		if ({if !$attribute->isRequired() || ($attribute->_lazyLoad && !$attribute->_table && $attribute->_column && !$attribute->_cardinality)}$appendDirty && !$this->recordExists && {/if}!$this->isDirty('{$attribute->_name}') && !{if $attribute->_cardinality}count{else}isset{/if}($this->_{$attribute->_name}) && !in_array('{$attribute->_name}', $initKeys)) {ldelim}
			$this->set{$attribute->getMethodName()}($this->getDefaultAttributeValue('{$attribute->_name}'), FALSE);
		{rdelim}
{/if}
{/foreach}

  {include file="entity-aspect-after.tpl"}
        
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
  
  // public methods 
  
	// {ldelim}{ldelim}{ldelim} copy
	/**
	 * returns a copy of this instance of {$className}. all set attributes will be 
   * dirty. {if $primaryKey}no primary key will be set. use insert to add the copy to the database.
{/if}
   * @param boolean $recursive whether or not to perform the copy recursively. 
   * when TRUE, any nested entity attributes will also be copied. otherwise, 
   * the copy will contain references to the same entities
   * @access public
	 * @return {$className}
	 */
	function &copy($recursive=FALSE) {ldelim}
{if !$entity->_skipPersistence}
    static $_copying = array();
    // avoid recursive loops
    if ($recursive && $_copying[$this->getPrimaryKey()]) {ldelim}
      $nl = NULL;
      return $nl;
    {rdelim}
    
    if ($recursive) {ldelim} $_copying[$this->getPrimaryKey()] = TRUE; {rdelim}
{/if}
    $initVals = array();
{foreach from=$entity->getAttributes() item=attribute}
{if $primaryKey->_name neq $attribute->_name && !$attribute->_setOnly && !$entity->excludeAttrFromRender($attribute->_name)}
    if ({if $attribute->_cardinality}count{/if}($attr ={if $attribute->_useReference}&{/if} $this->get{$attribute->getMethodName()}()){if !$attribute->_cardinality} !== NULL{/if}) {ldelim}
{if $attribute->_cardinality}
      $initVals['{$attribute->_name}'] = array();
      $keys = array_keys($attr);
      foreach($keys as $key) {ldelim}
{/if}
{if $attribute->isEntity()}
      if ($recursive) {ldelim}
        $initVals['{$attribute->_name}']{if $attribute->_cardinality}[$key]{/if} =& $attr{if $attribute->_cardinality}[$key]{/if}->copy(TRUE);
      {rdelim}
      else {ldelim}
{/if}
        $initVals['{$attribute->_name}']{if $attribute->_cardinality}[$key]{/if} = {if $attribute->_isFile}$attr{if $attribute->_cardinality}[$key]{/if}->copy(){else}$attr{if $attribute->_cardinality}[$key]{/if}{/if};
{if $attribute->isEntity()}
      {rdelim}
{/if}
{if $attribute->_cardinality}
      {rdelim}
{/if}
    {rdelim}
{/if}
{/foreach}
{if !$entity->_skipPersistence}
    if ($recursive) {ldelim} unset($_copying[$this->getPrimaryKey()]); {rdelim}
{/if}
    return new {$className}($initVals);
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
	
{if $primaryKey}
	// {ldelim}{ldelim}{ldelim} equals
	/**
	 * Determines whether or not this object references the same entity as another
	 * @param Object $object the object to compare with. both the type and 
	 * primary key will be checked. if this is an array of {$className} 
	 * objects, each object in this array will be checked and the method will 
	 * return TRUE if this object is equal to any of them
   * @access public
	 * @return String
	 */
	function equals(& $object) {ldelim}
    {$Template->assign('aopMethodName', "equals")}
    {include file="entity-aspect-before.tpl"}
    $ret = FALSE;
		if (!is_array($object)) {ldelim}
			$ret = ({$className}::isValid($object) && $object->getPrimaryKey() === $this->getPrimaryKey());
		{rdelim}
		else {ldelim}
			$keys = array_keys($object);
			foreach ($keys as $key) {ldelim}
				if ({$className}::isValid($object[$key]) && $object[$key]->getPrimaryKey() === $this->getPrimaryKey()) {ldelim}
					$ret = TRUE;
          break;
				{rdelim}
			{rdelim}
		{rdelim}
    {include file="entity-aspect-after.tpl"}
    return $ret;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
{/if}
	

	//*** GETTERS ***//
	// {ldelim}{ldelim}{ldelim} getAttribute
	/**
	 * Returns the value of an attribute based on its name. Masks _getAttribute in 
	 * order to allow for parent classes to override, but still use that method
	 * 
   * @param string $name the name of the attribute to return
   * @param boolean $clean whether or not to return the non-dirty value for the attribute
   * @param mixed $pk if the attribute specified is an entity with cardinality, 
   * the primary key of the value to return
	 * @return mixed
	 * @access public
	 */
	function &getAttribute($name, $clean=FALSE, $pk=NULL) {ldelim}
    {$Template->assign('aopMethodName', "getAttribute")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
		return $this->_getAttribute($name, $clean, $pk);
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
	// {ldelim}{ldelim}{ldelim} getAttributeCardinality
	/**
	 * returns the cardinality used by the attribute $name or NULL if that 
   * attribute does not use cardinality (1..1). when a cardinality value is 
   * returned, it will be in the format "[lower bound]..[upper bound]". for 
   * example: "1..3" or "0..2147483647" (the latter is generally returned when 
   * the upper bound is not specified "0..*")
   * @param string $name the name of the attribute to return the cardinality for
   * @param int $bound whether to return the lowerbound cardinality limit (when 
   * $bound === 0), the upperbound cardinality limit (when $bound === 1) or the 
   * full cardinality expression ($bound === NULL)
   * @param boolean $useWildcard when the upper bound is unlimited and this 
   * parameter is TRUE, the upperbound value will be "*"
	 * @return mixed
	 * @access public
	 */
	function getAttributeCardinality($name, $bound=NULL, $useWildcard=TRUE) {ldelim}
    {$Template->assign('aopMethodName', "getAttributeCardinality")}
    {include file="entity-aspect-before.tpl"}
    $cardinality = NULL;
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_cardinality}
    if ('{$attribute->_name}' == $name) {ldelim} $cardinality = $bound === NULL ? '{$attribute->_cardinalityLower}..' . ($useWildcard && {$attribute->_cardinalityUpper} == SRA_MAX_INT_VAL ? '*' : '{$attribute->_cardinalityUpper}') : ($bound === 0 ? {$attribute->_cardinalityLower} : ($useWildcard && {$attribute->_cardinalityUpper} == SRA_MAX_INT_VAL ? '*' : '{$attribute->_cardinalityUpper}')); {rdelim}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
    return $cardinality;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
	// {ldelim}{ldelim}{ldelim} getAttributeNames
	/**
	 * Returns an array of all of the attribute names for this entity including 
   * aggregate attributes
	 * @return array
	 * @access public
	 */
	function getAttributeNames() {ldelim}
    $names = array();
{foreach from=$entity->getAttributes() item=attribute}
    $names[] = '{$attribute->_name}';
{if $attribute->getAggregateAttributes()}
    // aggregate attributes from {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
    $names[] = '{$attr->_name}';
{/foreach}
    
{/if}
{/foreach}
    return $names;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
	// {ldelim}{ldelim}{ldelim} getAttributeType
	/**
	 * Returns the data type of the attribute specified
	 * 
   * @param string $name the name of the base attribute to return the type of
	 * @return String
	 * @access public
	 */
	function getAttributeType($name) {ldelim}
    {$Template->assign('aopMethodName', "getAttributeType")}
    {include file="entity-aspect-before.tpl"}
    $type = NULL;
{foreach from=$entity->getAttributes() item=attribute}
    if ($name == '{$attribute->_name}') {ldelim} $type = '{$attribute->_type}'; {rdelim}
{/foreach}
    {include file="entity-aspect-after.tpl"}
    return $type;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
	// {ldelim}{ldelim}{ldelim} getAttributeTypesUsed
	/**
	 * returns an array of all of the types (scalar and complex) used by this 
   * entity or a boolean value if $type is specified
   * @param string $type if specified, this method will return TRUE if this 
   * entity uses $type, FALSE otherwise. if $type is boolean and TRUE, ONLY 
   * complex (entity) types will be returned
	 * @return mixed
	 * @access public
	 */
	function getAttributeTypesUsed($type=NULL) {ldelim}
    {$Template->assign('aopMethodName', "usesAttributeType")}
    {include file="entity-aspect-before.tpl"}
    
    static $_{$entity->_name}TypesUsed;
    static $_{$entity->_name}ComplexTypesUsed;
    
    if (!$_{$entity->_name}TypesUsed) {ldelim}
      $_{$entity->_name}TypesUsed = array({assign var="started" value="0"}{foreach from=$entity->getTypesUsed() item=type}{if $started}, {/if}'{$type}'{assign var="started" value="1"}{/foreach});
      $_{$entity->_name}ComplexTypesUsed = array({assign var="started" value="0"}{foreach from=$entity->getTypesUsed(1) item=type}{if $started}, {/if}'{$type}'{assign var="started" value="1"}{/foreach});
    {rdelim}
    {include file="entity-aspect-after.tpl"}
    return $type ? ($type === TRUE ? $_{$entity->_name}ComplexTypesUsed : in_array($type, $_{$entity->_name}TypesUsed)) : $_{$entity->_name}TypesUsed;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
	// {ldelim}{ldelim}{ldelim} attributeIsEntity
	/**
	 * returns TRUE if the attribute $name is an entity type attribute
   * @param string $name the name of the entity
	 * @return boolean
	 * @access public
	 */
	function attributeIsEntity($name) {ldelim}
    {$Template->assign('aopMethodName', "attributeIsEntity")}
    {include file="entity-aspect-before.tpl"}
    
    $isEntity = FALSE;
    
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->isEntity()}
    if ($name == '{$attribute->_name}') {ldelim} $isEntity = TRUE; {rdelim}
{/if}
{/foreach}

    {include file="entity-aspect-after.tpl"}
    return $isEntity;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
	// {ldelim}{ldelim}{ldelim} attributesUseFiles
	/**
	 * returns TRUE if this entity or any of its' sub-entities use file type 
   * attributes
	 * @return boolean
	 * @access public
	 */
	function attributesUseFiles() {ldelim}
    {$Template->assign('aopMethodName', "attributesUseFiles")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    return {if $entity->usesFiles()}TRUE{else}FALSE{/if};
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
	// {ldelim}{ldelim}{ldelim} isAttribute
	/**
	 * returns TRUE if this entity contains an attribute by the name $attr
   * @param string $attr the name of the attribute to check for
	 * @return boolean
	 * @access public
	 */
	function isAttribute($attr) {ldelim}
    {$Template->assign('aopMethodName', "isAttribute")}
    {include file="entity-aspect-before.tpl"}
    $found = FALSE;
{foreach from=$entity->getAttributes() item=attribute}
    if ($attr == '{$attribute->_name}') {ldelim} $found = TRUE; {rdelim}
{if $attribute->getAggregateAttributes()}
    // aggregate attributes from {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
    if ($attr == '{$attr->_name}') {ldelim} $found = TRUE; {rdelim}
{/foreach}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
    return $found;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	// {ldelim}{ldelim}{ldelim} _getAttribute
	/**
	 * Returns the value of an attribute based on its name
	 * 
   * @param string $name the name of the attribute to return
   * @param boolean $clean whether or not to return the non-dirty value for the attribute
   * @param mixed $pk if the attribute specified is an entity with cardinality, 
   * the primary key of the value to return
	 * @return 
	 * @access public
	 */
	function &_getAttribute($name, $clean=FALSE, $pk=NULL) {ldelim}
    {$Template->assign('aopMethodName', "_getAttribute")}
    {include file="entity-aspect-before.tpl"}
    
    $guessedPk = FALSE;
		if (!isset($pk) && count($pieces = explode('_', $name)) > 1) {ldelim}
			$pk = $pieces[1];
      $guessedPk = TRUE;
		{rdelim}
    
    $ret = NULL;
		if (method_exists($this, $name)) {ldelim}
			$ret =& $this->${ldelim}name{rdelim}();
		{rdelim}
    else if (count($pieces = explode('_', $name)) > 1 && method_exists($this, $pieces[0])) {ldelim}
      $name = $pieces[0];
      $subAttr = NULL;
      for($i=1; $i<count($pieces); $i++) {ldelim}
        $subAttr .= $subAttr !== NULL ? '_' : '';
        $subAttr .= $pieces[$i];
      {rdelim}
      $value =& $this->${ldelim}name{rdelim}();
      $single = FALSE;
      if (!is_array($value)) {ldelim} 
        $value = array($value);
        $single = TRUE;
      {rdelim}
      $ret = array();
      $keys = array_keys($value);
      foreach($keys as $key) {ldelim}
        if ($subAttr && is_object($value[$key]) && method_exists($value[$key], 'getAttribute')) {ldelim}
          $ret[] =& $value[$key]->getAttribute($subAttr);
        {rdelim}
        else {ldelim}
          $ret[] =& $value[$key];
        {rdelim}
      {rdelim}
      if ($single) {ldelim} $ret = isset($ret[0]) ? $ret[0] : NULL; {rdelim}
    {rdelim}
{foreach from=$entity->getAttributes() item=attribute}
		else if ('{$attribute->_name}' == $name) {ldelim}
			$ret =& $this->get{$attribute->getMethodName()}($clean);
		{rdelim}
{if $attribute->isEntity() || $attribute->_isFile}
		else if (strpos($name, '{$attribute->_name}_') === 0 && ({if $attribute->_cardinality}$pk && {/if}{if $attribute->isEntity()}{$attribute->_type}{$entity->_voSuffix}{else}SRA_FileAttribute{/if}::isValid($attr ={if $attribute->_useReference}& {/if}$this->get{$attribute->getMethodName()}({if $attribute->_cardinality}$pk, {/if}$clean)){if $attribute->_cardinality} || ((!$pk || $guessedPk) && is_array($attr ={if $attribute->_useReference}& {/if}$this->get{$attribute->getMethodName()}(NULL, $clean))){/if})) {ldelim}
			$attrName = str_replace('{$attribute->_name}_', '', $name);
{if $attribute->_cardinality}
			if ($pk && !is_array($attr)) {ldelim}
				$attrName = str_replace($pk . '_', '', $attrName);
			{rdelim}
      if (is_array($attr)) {ldelim}
        $ret = array();
        $keys = array_keys($attr);
        foreach($keys as $key) {ldelim}
          if ({if $attribute->isEntity()}{$attribute->_type}{$entity->_voSuffix}{else}SRA_FileAttribute{/if}::isValid($attr[$key])) {ldelim}
{if $attribute->isEntity()}
			      $ret[] =& $attr[$key]->getAttribute($attrName, $clean, $pk);
{else}
            $ret[] =& $attr[$key]->${ldelim}attrName{rdelim}();
{/if}
          {rdelim}
        {rdelim}
      {rdelim}
      else {ldelim}
{/if}
{if $attribute->isEntity()}
			$ret =& $attr->getAttribute($attrName, $clean, $pk);
{else}
      $ret =& $attr->${ldelim}attrName{rdelim}();
{/if}
{if $attribute->_cardinality}
      {rdelim}
{/if}
		{rdelim}
{/if}
{if $attribute->getAggregateAttributes()}
    // mapped attributes for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
    if ('{$attr->_name}' == $name) {ldelim}
      $ret ={if $attr->_useReference}&{/if} $this->get{$attr->getMethodName()}({if $attr->_cardinality && $attr->isEntity()}$pk, {/if}$clean);
    {rdelim}
{/foreach}
{/if}
{/foreach}

    {include file="entity-aspect-after.tpl"}

		return $ret;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}

  
	// {ldelim}{ldelim}{ldelim} getUnitTestInstance
	/**
	 * returns a new instance of the unit test for this entity applicable (must 
   * be defined using the 'unit-test' element in the entity defnition), 
   * otherwise returns NULL
	 * @return SRA_TestCase
	 * @access public
	 */
	function &getUnitTestInstance() {ldelim}
    {$Template->assign('aopMethodName', "getUnitTestInstance")}
    {include file="entity-aspect-before.tpl"}
    $ret = NULL;
{if $entity->_unitTest}
    include_once('{$entity->_unitTest}');
    $ret = new {$entity->_unitTestClass}();
{/if}
    {include file="entity-aspect-after.tpl"}
		return $ret;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
	
{foreach from=$entity->getAttributes() item=attribute}
{assign var="methodName" value="get"|cat:$attribute->getMethodName()}
	// {ldelim}{ldelim}{ldelim} {$methodName}
	/**
	 * Getter for <code>_{$attribute->_name}</code>
	 * {if $attribute->_apiResource}{$resources->getString($attribute->_apiResource)}{/if} 
	 * 
{if $attribute->_cardinality && $attribute->isEntity()}
   * @param mixed $pk the primary key of the {$attribute->_type} to return. if not specified, all {$attribute->_type} instances for this attribute will be returned. {if $attribute->isEntity()}if === 0, the first value will be returned{/if}
{/if}
   * @param $clean whether or not to return the non-dirty value for the attribute
{if $attribute->_cardinality}
   * @param int $index if you want this method to return a specific array index 
   * value. this parameter may be used to specify that index where 0 is the 
   * first array element, 1 is the second, and count(...)-1 or -1 is the last
{/if}
{if $attribute->hasOptions()}
   * @param $optionLabel whether or not to return the option label instead of 
   * the actual attribute  value
{/if}
{if !$attribute->_cardinality && ($attribute->_type eq $smarty.const.SRA_DATA_TYPE_DATE || $attribute->_type eq $smarty.const.SRA_DATA_TYPE_TIME)}
   * @param string $format if you want a formatted date string instead of a 
   * reference to the SRA_GregorianDate object itself, you may specify a date format 
   * string using this parameter. You may set this parameter to TRUE or 1 to use
{if $attribute->_dateFormat}
   * the custom "date-format" {$attribute->_dateFormat} specified for this attribute
{else}
   * the app SRA_Controller::getAppDate{if $attribute->_type eq $smarty.const.SRA_DATA_TYPE_DATE}Only{/if}Format() format
{/if}
{/if}
{if $attribute->_recursiveLink || $attribute->_unionLink}
   * @param boolean $unlinkedOnly whether or not to ONLY return unlinked values
{/if}
	 * @return {if $attribute->_isFile}SRA_FileAttribute{else}{$attribute->_type}{/if}{if $attribute->_cardinalityUpper > 1}[]{/if}

	 * @access public
	 */
	function {if $attribute->_useReference}&{/if}{$methodName}({if $attribute->_cardinality && $attribute->isEntity()}$pk = NULL, {/if}$clean=FALSE{if $attribute->_cardinality}, $index=NULL{/if}{if !$attribute->_cardinality && ($attribute->_type eq $smarty.const.SRA_DATA_TYPE_DATE || $attribute->_type eq $smarty.const.SRA_DATA_TYPE_TIME)}, $format=NULL{/if}{if $attribute->hasOptions()}, $optionLabel=FALSE{/if}{if $attribute->_recursiveLink || $attribute->_unionLink}, $unlinkedOnly = FALSE{/if}) {ldelim}
    {$Template->assign('aopMethodName', $methodName)}
    {include file="entity-aspect-before.tpl"}
    
{if $attribute->_matchUserId}
    if (!$this->_matchUserId('{$attribute->_matchUserId}', 'get{$attribute->getMethodName()}')) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return;
    {rdelim}
{/if}
{if $attribute->_cardinality}
    if ({if $attribute->isEntity()}!isset($pk) && {/if}isset($index)) {ldelim}
      $val = NULL;
      if (($attrs =& $this->{$methodName}({if $attribute->isEntity()}NULL, {/if}$clean, NULL{if !$attribute->_cardinality && ($attribute->_type eq $smarty.const.SRA_DATA_TYPE_DATE || $attribute->_type eq $smarty.const.SRA_DATA_TYPE_TIME)}, $format{/if}{if $attribute->hasOptions()}, $optionLabel{/if}{if $attribute->_recursiveLink || $attribute->_unionLink}, $unlinkedOnly{/if})) && ($keys = array_keys($attrs)) && ($key = $index == -1 ? $keys[count($keys) - 1] : $keys[$index]) !== NULL) {ldelim}
        $val =& $attrs[$key];
      {rdelim}
      {include file="entity-aspect-after.tpl"}
      return $val;
    {rdelim}
{/if}
    if ($clean && isset($this->_clean['{$attribute->_name}'])) {ldelim}
{if $attribute->_cardinality && $attribute->isEntity()}
      {include file="entity-aspect-after.tpl"}
      if ($pk && $this->_clean['{$attribute->_name}'][$pk]) {ldelim}
        return {if $attribute->hasOptions()}$optionLabel ? $this->getOptionLabel('{$attribute->_name}', $this->_clean['{$attribute->_name}'][$pk]) : {/if}$this->_clean['{$attribute->_name}'][$pk];
      {rdelim}
{/if}
{if !$attribute->_cardinality && ($attribute->_type eq $smarty.const.SRA_DATA_TYPE_DATE || $attribute->_type eq $smarty.const.SRA_DATA_TYPE_TIME)}
      if ($format && SRA_GregorianDate::isValid($this->_clean['{$attribute->_name}'])) {ldelim} 
        return $this->_clean['{$attribute->_name}']->format($format === 1 || $format === TRUE ? {if $attribute->_dateFormat}'{$attribute->_dateFormat}'{else}NULL{/if} : $format);
      {rdelim}
{/if}
      return {if $attribute->hasOptions()}$optionLabel ? $this->getOptionLabel('{$attribute->_name}', $this->_clean['{$attribute->_name}']) : {/if}$this->_clean['{$attribute->_name}'];
    {rdelim}
{if $attribute->_cardinality}
		if (count($this->_{$attribute->_name}){if $attribute->isEntity()} && $pk && isset($this->_{$attribute->_name}[$pk]){/if}) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return {if $attribute->hasOptions()}$optionLabel ? $this->getOptionLabel('{$attribute->_name}', $this->_{$attribute->_name}{if $attribute->isEntity()}[$pk]{/if}) : {/if}$this->_{$attribute->_name}{if $attribute->isEntity()}[$pk]{/if};
		{rdelim}
{if $attribute->isEntity()}
    // return first instance
    else if ($pk === 0 && count($this->get{$attribute->getMethodName()}())) {ldelim}
      {include file="entity-aspect-after.tpl"}
      $keys = array_keys($this->_{$attribute->_name});
			return $this->_{$attribute->_name}[$keys[0]];
    {rdelim}
{/if}
{/if}
{if $entity->attrIsPersistent($attribute->_name) && ($attribute->_lazyLoad || $attribute->_lazyLoadExclusive)}
		// load attribute if it is not already loaded (lazy load)
		if ({if !$attribute->_cardinality}!$this->hasBeenSet('{$attribute->_name}') && {/if}({if $attribute->_cardinality}({if $attribute->isEntity()}$pk && {/if}!isset($this->_lazyLoaded['{$attribute->_name}'{if $attribute->isEntity()} . $pk{/if}])) || ({if $attribute->isEntity()}!$pk && {/if}{/if}!isset($this->_lazyLoaded['{$attribute->_name}']) && !{if $attribute->_cardinality}count{else}isset{/if}($this->_{$attribute->_name}){if $attribute->_cardinality}){/if}) && $this->recordExists) {ldelim}
			$this->_lazyLoaded['{$attribute->_name}'{if $attribute->_cardinality && $attribute->isEntity()} . $pk{/if}] = TRUE;
			$dao =& SRA_DaoFactory::getDao('{$entity->_name}');
{if $attribute->_cardinality && $attribute->isEntity()}
			if (!$pk) {ldelim}
{/if}
				$val = &$dao->get{$attribute->getMethodName()}($this);
{if $attribute->_cardinality}
				if (is_array($val) && count($val)) {ldelim}
          $vkeys = array_keys($val);
          foreach($vkeys as $vkey) {ldelim}
            if (is_object($val[$vkey])) {ldelim} $this->_lazyLoaded['{$attribute->_name}' . $val[$vkey]->getPrimaryKey()] = {if $attribute->_useReference}&{/if}$val[$vkey]; {rdelim}
          {rdelim}
{else}
{if $attribute->_type eq $smarty.const.SRA_DATA_TYPE_BOOLEAN}
				if ($val == 1 || $val == 0) {ldelim}
{else}
				if ($val) {ldelim}
{/if}
{/if}
					$this->{if $attribute->_cardinality}add{else}set{/if}{$attribute->getMethodName()}($val, FALSE);
				{rdelim}
{if $attribute->_cardinality && $attribute->isEntity()}
			{rdelim}
			else {ldelim}
				$val = &$dao->get{$attribute->getMethodName()}($this, $pk);
				$this->_lazyLoaded['{$attribute->_name}' . $pk] = {if $attribute->_useReference}&{/if}$val;
			{rdelim}
{elseif $attribute->_cardinality}
			$this->_lazyLoaded['{$attribute->_name}'] ={if $attribute->_useReference}& {/if}$val;
{/if}
		{rdelim}
{elseif !$attribute->getMappedAttributes() && $attribute->_table}
		if ($this->_{$attribute->_name} === SRA_ENTITY_ATTRIBUTE_CIRC_REF) {ldelim}
			$dao =& SRA_DaoFactory::getDao('{$entity->_name}');
			$this->set{$attribute->getMethodName()}($dao->get{$attribute->getMethodName()}($this), FALSE);
		{rdelim}
{elseif $attribute->getMappedAttributes()}
		if (!$this->_{$attribute->_name}) {ldelim}
      require_once('{$attribute->_type}{$entity->_voSuffix}.{$smarty.const.SRA_SYS_PHP_EXTENSION}');
			$this->_{$attribute->_name} = new {$attribute->_type}{$entity->_voSuffix}();
		{rdelim}
{/if}
{if $attribute->_recursiveLink}
{if $attribute->_name eq $attribute->_recursiveLink}
    if ({if $attribute->_cardinality}(!$pk && ($attr =& $this->_{$attribute->_name})) || ($pk && isset($this->_lazyLoaded['{$attribute->_name}' . $pk])){else}$attr =& $this->_{$attribute->_name}{/if}) {ldelim}
{if $attribute->_cardinality}
      if ($pk) {ldelim}
        $attr =& $this->get{$attribute->getMethodName()}();
        return isset($attr[$pk]) ? ({if $attribute->hasOptions()}$optionLabel ? $this->getOptionLabel('{$attribute->_name}', $attr[$pk]) : {/if}$attr[$pk]) : NULL;
      {rdelim}
{/if}
{else}
    if ($attr =& $this->getAttribute('{$attribute->_recursiveLink}')) {ldelim}
{/if}
      $linkVals = array();
      if (is_array($attr)) {ldelim}
        $keys = array_keys($attr);
        foreach ($keys as $key) {ldelim}
          $tmp = $attr[$key]->getAttribute('{$attribute->_name}');
          if (is_array($tmp)) {ldelim}
            $tkeys = array_keys($tmp);
            foreach ($tkeys as $tkey) {ldelim}
              $linkVals[] = $tmp[$tkey];
            {rdelim}
          {rdelim}
          else {ldelim}
            $linkVals[] = $tmp;
          {rdelim}
        {rdelim}
      {rdelim}
      else {ldelim}
        $tmp = $attr->getAttribute('{$attribute->_name}');
        if (is_array($tmp)) {ldelim}
          $tkeys = array_keys($tmp);
          foreach ($tkeys as $tkey) {ldelim}
            $linkVals[] = $tmp[$tkey];
          {rdelim}
        {rdelim}
        else {ldelim}
          $linkVals[] = $tmp;
        {rdelim}
      {rdelim}
      if (!is_array($this->_{$attribute->_name})) {ldelim}
        $this->_{$attribute->_name} = array($this->_{$attribute->_name});
      {rdelim}
      $keys = array_keys($linkVals);
      foreach($keys as $key) {ldelim}
        if (is_object($linkVals[$key]) && method_exists($linkVals[$key], 'getPrimaryKey')) {ldelim}
          if (!isset($this->_{$attribute->_name}[$linkVals[$key]->getPrimaryKey()])) {ldelim}
            if (!is_array($this->_linkedAttributes['{$attribute->_name}'])) {ldelim}
              $this->_linkedAttributes['{$attribute->_name}'] = array();
            {rdelim}
            $this->_linkedAttributes['{$attribute->_name}'][$linkVals[$key]->getPrimaryKey()] = TRUE;
            $this->_{$attribute->_name}[$linkVals[$key]->getPrimaryKey()] = $linkVals[$key];
          {rdelim}
        {rdelim}
        else {ldelim}
          $this->_{$attribute->_name}[] = $linkVals[$key];
        {rdelim}
      {rdelim}
    {rdelim}
{/if}
{if $attribute->_unionLink}
    if ($attr =& $this->getAttribute('{$attribute->_unionLink}')) {ldelim}
      $linkVals = array();
      if (is_array($attr)) {ldelim}
        $keys = array_keys($attr);
        foreach ($keys as $key) {ldelim}
          $tmp = $attr[$key];
          if (is_array($tmp)) {ldelim}
            $tkeys = array_keys($tmp);
            foreach ($tkeys as $tkey) {ldelim}
              $linkVals[] = $tmp[$tkey];
            {rdelim}
          {rdelim}
          else {ldelim}
            $linkVals[] = $tmp;
          {rdelim}
        {rdelim}
      {rdelim}
      else {ldelim}
        $tmp = $attr;
        if (is_array($tmp)) {ldelim}
          $tkeys = array_keys($tmp);
          foreach ($tkeys as $tkey) {ldelim}
            $linkVals[] = $tmp[$tkey];
          {rdelim}
        {rdelim}
        else {ldelim}
          $linkVals[] = $tmp;
        {rdelim}
      {rdelim}
      if (!is_array($this->_{$attribute->_name})) {ldelim}
        $this->_{$attribute->_name} = array($this->_{$attribute->_name});
      {rdelim}
      $keys = array_keys($linkVals);
      foreach($keys as $key) {ldelim}
        if (is_object($linkVals[$key]) && method_exists($linkVals[$key], 'getPrimaryKey')) {ldelim}
          if (!isset($this->_{$attribute->_name}[$linkVals[$key]->getPrimaryKey()])) {ldelim}
            if (!is_array($this->_linkedAttributes['{$attribute->_name}'])) {ldelim}
              $this->_linkedAttributes['{$attribute->_name}'] = array();
            {rdelim}
            $this->_linkedAttributes['{$attribute->_name}'][$linkVals[$key]->getPrimaryKey()] = TRUE;
            $this->_{$attribute->_name}[$linkVals[$key]->getPrimaryKey()] = $linkVals[$key];
          {rdelim}
        {rdelim}
        else {ldelim}
          $this->_{$attribute->_name}[] = $linkVals[$key];
        {rdelim}
      {rdelim}
    {rdelim}
{/if}
{if $attribute->_cardinality && $attribute->isEntity()}
    if (!$pk) {ldelim}
      {include file="entity-aspect-after.tpl"}
{if $attribute->_recursiveLink || $attribute->_unionLink}
      if ($unlinkedOnly) {ldelim}
        $ret = array();
        $keys = array_keys($this->_{$attribute->_name});
        foreach ($keys as $key) {ldelim}
          if (!isset($this->_linkedAttributes['{$attribute->_name}'][$key])) {ldelim}
            $ret[$key] ={if $attribute->_useReference}&{/if} $this->_{$attribute->_name}[$key];
          {rdelim}
        {rdelim}
        return $ret;
      {rdelim}
{/if}
      return isset($this->_{$attribute->_name}) ? $this->_{$attribute->_name} : NULL;
    {rdelim}
    else {ldelim}
      {include file="entity-aspect-after.tpl"}
      return {if $attribute->_recursiveLink || $attribute->_unionLink}isset($this->_{$attribute->_name}[$pk]) ? $this->_{$attribute->_name}[$pk] : {/if}(isset($this->_lazyLoaded['{$attribute->_name}' . $pk]) ? $this->_lazyLoaded['{$attribute->_name}' . $pk] : NULL);
    {rdelim}
{elseif $attribute->_cardinality}
    {include file="entity-aspect-after.tpl"}
{if $attribute->_recursiveLink || $attribute->_unionLink}
    if ($unlinkedOnly) {ldelim}
      $ret = array();
      $keys = array_keys($this->_{$attribute->_name});
      foreach ($keys as $key) {ldelim}
        if (!in_array($this->_{$attribute->_name}[$key], $this->_linkedAttributes['{$attribute->_name}'])) {ldelim}
          $ret[] = $this->_{$attribute->_name}[$key];
        {rdelim}
      {rdelim}
      return $ret;
    {rdelim}
{/if}
    return isset($this->_lazyLoaded['{$attribute->_name}']) ? $this->_{$attribute->_name} : NULL;
{else}
    {include file="entity-aspect-after.tpl"}
{if !$attribute->_cardinality && ($attribute->_type eq $smarty.const.SRA_DATA_TYPE_DATE || $attribute->_type eq $smarty.const.SRA_DATA_TYPE_TIME)}
    if ($format && SRA_GregorianDate::isValid($this->_{$attribute->_name})) {ldelim} 
      return $this->_{$attribute->_name}->format($format === 1 || $format === TRUE ? {if $attribute->_dateFormat}'{$attribute->_dateFormat}'{else}NULL{/if} : $format);
    {rdelim}
{/if}
    return isset($this->_{$attribute->_name}) ? ({if $attribute->hasOptions()}$optionLabel ? $this->getOptionLabel('{$attribute->_name}', $this->_{$attribute->_name}) : {/if}$this->_{$attribute->_name}) : NULL;
{/if}
		
	{rdelim}
	// {rdelim}{rdelim}{rdelim}


{if $attribute->_type eq $smarty.const.SRA_DATA_TYPE_BOOLEAN && !$attribute->_cardinality}
{assign var="isMethodName" value="is"|cat:$attribute->getMethodName()}
	// {ldelim}{ldelim}{ldelim} {$isMethodName}
	/**
	 * Alias to {$methodName}. added because the attribute type is boolean
	 * 
   * @param $clean whether or not to return the non-dirty value for the attribute
	 * @return boolean
	 * @access public
	 */
	function {$isMethodName}($clean=FALSE) {ldelim}
    {$Template->assign('aopMethodName', $isMethodName)}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    return $this->{$methodName}($clean);
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
{/if}


{if $attribute->_cardinality}
{assign var="countMethodName" value=$methodName|cat:"Count"}
	// {ldelim}{ldelim}{ldelim} {$countMethodName}
	/**
	 * returns the size of the {$attribute->_name} array
   * @param $clean whether or not to return the count for the non-dirty values 
   * for the attribute
	 * @return int
	 * @access public
	 */
	function {$countMethodName}($clean=FALSE) {ldelim}
    {$Template->assign('aopMethodName', $countMethodName)}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    $attrs =& $this->{$methodName}($clean);
    return $attrs ? count($attrs) : 0;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
{/if}

{if $attribute->getAggregateAttributes()}
    // mapped getters for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{if !$attr->_setOnly}
{assign var="methodName" value="get"|cat:$attr->getMethodName()}
	// {ldelim}{ldelim}{ldelim} {$methodName}
	/**
	 * Getter for <code>_{$attribute->_name}.{$attr->_name}</code>
	 * {if $attr->_apiResource}{$resources->getString($attr->_apiResource)}{/if} 
	 * 
   * @param $clean whether or not to return the non-dirty value for the attribute
	 * @return {if $attr->_isFile}SRA_FileAttribute{else}{$attr->_type}{/if}

	 * @access public
	 */
	function{if $attr->_useReference} &{/if} {$methodName}({if $attr->_cardinality && $attr->isEntity()}$pk = FALSE, {/if}$clean=FALSE) {ldelim}
    {$Template->assign('aopMethodName', $methodName)}
    {include file="entity-aspect-before.tpl"}
    require_once('{$attribute->_type}{$entity->_voSuffix}.{$smarty.const.SRA_SYS_PHP_EXTENSION}');
    if (!{$attribute->_type}{$entity->_voSuffix}::isValid($this->get{$attribute->getMethodName()}())) {ldelim}
      $attr = new {$attribute->_type}{$entity->_voSuffix}();
      $val = $attr->get{$attr->getMethodName(0, 1)}({if $attr->_cardinality && $attr->isEntity()}$pk, {/if}$clean);
    {rdelim}
    else {ldelim}
      $val = $this->_{$attribute->_name}->get{$attr->getMethodName(0, 1)}({if $attr->_cardinality && $attr->isEntity()}$pk = FALSE, {/if}$clean);
    {rdelim}
    {include file="entity-aspect-after.tpl"}
    return $val;
  {rdelim}
  // {rdelim}{rdelim}{rdelim}
  
{if $attr->_type eq $smarty.const.SRA_DATA_TYPE_BOOLEAN && !$attr->_cardinality}
{assign var="isMethodName" value="is"|cat:$attr->getMethodName()}
	// {ldelim}{ldelim}{ldelim} {$isMethodName}
	/**
	 * Alias to {$methodName}. added because the attribute type is boolean
	 * 
   * @param $clean whether or not to return the non-dirty value for the attribute
	 * @return boolean
	 * @access public
	 */
	function {$isMethodName}($clean=FALSE) {ldelim}
    {$Template->assign('aopMethodName', $isMethodName)}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    return $this->{$methodName}($clean);
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
{/if}
{/if}
{/foreach}
{/if}
{/foreach}


	// {ldelim}{ldelim}{ldelim} getAttrDbValue
	/**
	 * returns the $attr value for this object in a db prepared format
	 * 
	 * @param string $attr the name of the attribute. if not specified, it will be 
	 * assumed that the $attr is the primary key {$primaryKey->_name}
	 * @param int $value optional parameter used to specify a specific value to 
   * convert or for attributes where the cardinality upper bound is > 1. if 
   * specified, and the attribute is an entity, then the value should be the 
   * primary key of the entity to return. if the attribute is not an entity, 
   * then the value should be the actual value to convert
   * @param boolean $clean whether or not to return the clean value for the 
   * attribute if it is dirty
	 * @return string
	 * @access public
	 */
	function getAttrDbValue($attr=FALSE, $value=FALSE, $clean=FALSE) {ldelim}
    {$Template->assign('aopMethodName', "getAttrDbValue")}
    {include file="entity-aspect-before.tpl"}
		$db =& SRA_Controller::getAppDb({if $entity->_db}'{$entity->_db}'{/if});
		$attrPieces = explode('_', $attr);
		$baseAttr = $attr;
		$attr = $attrPieces[0];
		$entityAttr = FALSE;
		if (count($attrPieces) > 1) {ldelim}
			$entityAttr = substr($baseAttr, strlen($attr) + 1);
		{rdelim}
{foreach from=$entity->getAttributes() item=attribute}
{if !$attribute->_skipPersistence && !$entity->_customDao}
		if ('{$attribute->_name}' == $attr{if $attribute->_name eq $primaryKey->_name} || !$attr{/if}) {ldelim}
{if !$attribute->_cardinality || $attribute->isEntity() || $attribute->_aggregateCardinality}
      if (!$value) {ldelim}
			  $value ={if $attribute->_useReference}&{/if} $this->get{$attribute->getMethodName()}({if $attribute->_cardinality && $attribute->isEntity()}$value, {/if}$clean);
      {rdelim}
{/if}
{if !$attribute->isEntity()}
{if $attribute->_isFile}
      {include file="entity-aspect-after.tpl"}
			return SRA_FileAttribute::isValid($value) ? $value->getAppDbData($db) : $db->convertText({if $attribute->_nullDbEmptyStr}''{else}NULL{/if});
{else}
      {include file="entity-aspect-after.tpl"}
			return {if $attribute->_nullDbEmptyStr}$value === NULL ? "''" : {/if}$db->{$attribute->getConvertMethodName()}({if $attribute->_aggregateCardinality}implode('{$smarty.const.SRA_AGGREGATE_CARDINALITY_DELIM}', $value){else}$value{/if});
{/if}
{else}
{if !$attribute->getMappedAttributes()}
      if ({$attribute->_type}{$entity->_voSuffix}::isValid($value) && !$value->recordExists) {ldelim}
        $dao =& SRA_DaoFactory::getDao('{$attribute->_type}');
        $dao->insert($value);
      {rdelim}
{/if}
      {include file="entity-aspect-after.tpl"}
			return {$attribute->_type|cat:$entity->_voSuffix}::isValid($value) ? $value->getAttrDbValue($entityAttr) : $db->convertText({if $attribute->_nullDbEmptyStr}''{else}NULL{/if});
{/if}
		{rdelim}
{/if}
{if $attribute->getAggregateAttributes()}
    // mapped attributes for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
    if ('{$attr->_name}' == $attr) {ldelim}
      require_once('{$attribute->_type}{$entity->_voSuffix}.{$smarty.const.SRA_SYS_PHP_EXTENSION}');
      if (!{$attribute->_type}{$entity->_voSuffix}::isValid($this->get{$attribute->getMethodName()}())) {ldelim}
        $attr = new {$attribute->_type}{$entity->_voSuffix}();
        $ret = $attr->getAttrDbValue('{$attr->_baseName}', $value, $clean);
      {rdelim}
      else {ldelim}
        $ret = $this->_{$attribute->_name}->getAttrDbValue('{$attr->_baseName}', $value, $clean);
      {rdelim}
      {include file="entity-aspect-after.tpl"}
      return $ret;
    {rdelim}
{/foreach}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
		return $db->convertText(NULL);
	{rdelim}
	// {rdelim}{rdelim}{rdelim}


{if $primaryKey}
	//*** PRIMARY KEY ***//
	// {ldelim}{ldelim}{ldelim} getPrimaryKey
	/**
	 * Returns the primary key value for this entity
	 * 
	 * @return string
	 * @access public
	 */
	function getPrimaryKey() {ldelim}
    {$Template->assign('aopMethodName', "getPrimaryKey")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    return $this->get{$primaryKey->getMethodName()}();
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} getPrimaryKeyAttribute
	/**
	 * Returns the primary key attribute name for this entity
	 * 
	 * @return string
	 * @access public
	 */
	function getPrimaryKeyAttribute() {ldelim}
    return '{$primaryKey->_name}';
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} getPrimaryKeyColumn
	/**
	 * Returns the primary key column name for this entity
	 * 
	 * @return string
	 * @access public
	 */
	function getPrimaryKeyColumn() {ldelim}
    return '{$primaryKey->_column}';
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
{/if}


	// {ldelim}{ldelim}{ldelim} entityHasPersistence
	/**
	 * returns TRUE if this entity has persistence
	 * @return boolean
	 * @access public
	 */
	function entityHasPersistence() {ldelim}
    return {if $entity->_skipPersistence}FALSE{else}TRUE{/if};
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
{if $primaryKey}
	// {ldelim}{ldelim}{ldelim} getAppDbPrimaryKey
	/**
	 * Returns an associative array of primary key column/db formatted values for 
	 * this value object instance
	 * 
	 * @return string
	 * @access public
	 */
	function getAppDbPrimaryKey() {ldelim}
    {$Template->assign('aopMethodName', "getAppDbPrimaryKey")}
    {include file="entity-aspect-before.tpl"}
		$db =& SRA_Controller::getAppDb({if $entity->_db}'{$entity->_db}'{/if});
    {include file="entity-aspect-after.tpl"}
		return array('{$primaryKey->_column}' => $db->{$primaryKey->getConvertMethodName()}($this->_{$primaryKey->_name}));
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
{/if}


	//*** ATTRIBUTE LABELS ***//
	// {ldelim}{ldelim}{ldelim} getEntityLabel
	/**
	 * General method for retrieving the entity or attributes labels
	 * 
	 * @param string $attr the name of the attribute to return the label for. if 
	 * not specified, the label for this class will be returned
	 * @return string
	 * @access public
	 */
	function getEntityLabel($attr=FALSE) {ldelim}
    {$Template->assign('aopMethodName', "getEntityLabel")}
    {include file="entity-aspect-before.tpl"}
		if ($attr) {ldelim}
{foreach from=$entity->getAttributes() item=attribute}
			if ('{$attribute->_name}' == $attr) {ldelim}
        {include file="entity-aspect-after.tpl"}
				return $this->get{$attribute->getMethodName()}Label();
			{rdelim}
{if $attribute->isEntity()}
			if (strpos($attr, '{$attribute->_name}_') === 0) {ldelim}
				$attrName = str_replace('{$attribute->_name}_', '', $attr);
        {include file="entity-aspect-after.tpl"}
				return {$attribute->_type}{$entity->_voSuffix}::getEntityLabel($attrName);
			{rdelim}
{/if}
{if $attribute->getAggregateAttributes()}
      // mapped attributes for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
			if ('{$attr->_name}' == $attr) {ldelim}
        {include file="entity-aspect-after.tpl"}
				return $this->get{$attr->getMethodName()}Label();
			{rdelim}
{if $attr->isEntity()}
			if (strpos($attr, '{$attr->_name}_') === 0) {ldelim}
				$attrName = str_replace('{$attr->_name}_', '', $attr);
        {include file="entity-aspect-after.tpl"}
				return {$attr->_type}{$entity->_voSuffix}::getEntityLabel($attrName);
			{rdelim}
{/if}
{/foreach}
{/if}
{/foreach}
      {include file="entity-aspect-after.tpl"}
			return FALSE;
		{rdelim}
		else {ldelim}
			$rb =& {$className}::getEntityResources();
      {include file="entity-aspect-after.tpl"}
			return $rb->getString('{$entity->getResourceName()}');
		{rdelim}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
{foreach from=$entity->getAttributes() item=attribute}
{assign var="methodName" value="get"|cat:$attribute->getMethodName()|cat:"Label"}
	// {ldelim}{ldelim}{ldelim} {$methodName}
	/**
	 * Label getter for the <code>_{$attribute->_name}</code> label
	 * 
	 * @return string
	 * @access public
	 */
	function {$methodName}() {ldelim}
    {$Template->assign('aopMethodName', $methodName)}
    {include file="entity-aspect-before.tpl"}
		$rb =& {$className}::getEntityResources();
    {include file="entity-aspect-after.tpl"}
		return $rb->getString('{$attribute->getResourceName()}');
	{rdelim}
	// {rdelim}{rdelim}{rdelim}

{if $attribute->getAggregateAttributes()}
   // mapped label getters for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{assign var="methodName" value="get"|cat:$attr->getMethodName()|cat:"Label"}
	// {ldelim}{ldelim}{ldelim} {$methodName}
	/**
	 * Label getter for the <code>_{$attribute->_name}.{$attr->_name}</code> label
	 * 
	 * @return string
	 * @access public
	 */
	function {$methodName}() {ldelim}
    {$Template->assign('aopMethodName', $methodName)}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
		return {$attribute->_type}{$entity->_voSuffix}::get{$attr->getMethodName(0, 1)}Label();
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
{/foreach}
{/if}
{/foreach}


	// {ldelim}{ldelim}{ldelim} getHelpContent
	/**
	 * General method for retrieving the entity or attributes help content
	 * 
	 * @param string $attr the name of the attribute to return the help content 
	 * for. if not specified, the help content for this class will be returned
	 * @return string
	 * @access public
	 */
	function getHelpContent($attr=FALSE) {ldelim}
    {$Template->assign('aopMethodName', "getHelpContent")}
    {include file="entity-aspect-before.tpl"}
		if ($attr) {ldelim}
			$methodName = 'get' . strtoupper(substr($attr, 0, 1)) . substr($attr, 1) . 'HelpContent';
      {include file="entity-aspect-after.tpl"}
			if (method_exists($this, $methodName)) {ldelim}
        return $this->${ldelim}methodName{rdelim}();
      {rdelim}
      else {ldelim}
        $rb =& {$className}::getEntityResources();
        return $rb->containsKey('{$entity->_name}.' . $attr . '-help') ? $rb->getString('{$entity->_name}.' . $attr . '-help') : ($rb->containsKey('text.' . $attr . '-help') ? $rb->getString('text.' . $attr . '-help') : ($rb->containsKey($attr . '-help') ? $rb->getString($attr . '-help') : ''));
      {rdelim}
		{rdelim}
		else {ldelim}
			$rb =& {$className}::getEntityResources();
      {include file="entity-aspect-before.tpl"}
{if $entity->getHelpResourceName()}
			return $rb->getString('{$entity->getHelpResourceName()}');
{else}
			return '';
{/if}
		{rdelim}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
{foreach from=$entity->getAttributes() item=attribute}
{assign var="methodName" value="get"|cat:$attribute->getMethodName()|cat:"HelpContent"}
	// {ldelim}{ldelim}{ldelim} {$methodName}
	/**
	 * Help content getter for <code>_{$attribute->_name}</code>
	 * 
	 * @return string
	 * @access public
	 */
	function {$methodName}() {ldelim}
    {$Template->assign('aopMethodName', $methodName)}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
{if $attribute->_resourceHelp}
		$rb =& {$className}::getEntityResources();
		return $rb->getString('{$attribute->getHelpResourceName()}');
{else}
		return '';
{/if}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
{if $attribute->getAggregateAttributes()}
   // mapped help content for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{assign var="methodName" value="get"|cat:$attr->getMethodName()|cat:"HelpContent"}
	// {ldelim}{ldelim}{ldelim} {$methodName}
	/**
	 * Help content getter for <code>_{$attr->_name}</code>
	 * 
	 * @return string
	 * @access public
	 */
	function {$methodName}() {ldelim}
    {$Template->assign('aopMethodName', $methodName)}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    return {$attribute->_type}{$entity->_voSuffix}::get{$attr->getMethodName(0, 1)}HelpContent();
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
{/foreach}
{/if}
{/foreach}


	// {ldelim}{ldelim}{ldelim} getAddedVals
	/**
	 * Returns an array containing all of the values that have been added for a 
	 * given array attribute. if the attribute specified is not an array, or if 
	 * no values have been added, FALSE will be returned
	 * 
	 * @param string $attr the name of the attribute to return the values that 
	 * have been added for
	 * @return array
	 * @access public
	 */
	function &getAddedVals($attr) {ldelim}
    {$Template->assign('aopMethodName', "getAddedVals")}
    {include file="entity-aspect-before.tpl"}
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_cardinality}
		if ('{$attribute->_name}' == $attr && array_key_exists($attr, $this->_dirty) && array_key_exists(SRA_ATTRIBUTE_ADD_DIRTY_KEY, $this->_dirty[$attr])) {ldelim}
      {include file="entity-aspect-after.tpl"}
			return $this->_dirty[$attr][SRA_ATTRIBUTE_ADD_DIRTY_KEY];
		{rdelim}
{/if}
{if $attribute->getAggregateAttributes()}
   // mapped help content for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{if $attr->_cardinality}
		if ('{$attr->_name}' == $attr && $this->_{$attribute->_name} && $this->_{$attribute->_name}->isDirty('{$attr->_baseName}')) {ldelim}
      {include file="entity-aspect-after.tpl"}
			return $this->_{$attribute->_name}->getAddedVals('{$attr->_baseName}');
		{rdelim}
{/if}
{/foreach}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
{if $entity->_parentEntity}
		return parent::getAddedVals($attr);
{else}
		return FALSE;
{/if}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// {ldelim}{ldelim}{ldelim} getChangedVals
	/**
	 * Returns the changed values for a specific attribute, or for all changed 
	 * attributes. if the attribute specified has not been changed, then FALSE 
	 * will be returned. if no attribute is specified, and no non-array attributes 
	 * have been modified, then an empty array will be returned. if no attribute 
	 * is specified, then the return value will be an associative array indexed 
	 * by attribute name where the value is the changed value for that attribute. 
	 * otherwise, it is simply the changed value for the attribute specified. Only 
	 * non-array attribute change values will be returned using this method. for 
	 * array attributes, you must use the getAddedVals and getRemovedVals methods 
	 * get changes to that attribute.
	 * 
	 * @param string $attr the name of the attribute to return the changes values 
	 * for
	 * @return array
	 * @access public
	 */
	function &getChangedVals($attr = FALSE) {ldelim}
    {$Template->assign('aopMethodName', "getChangedVals")}
    {include file="entity-aspect-before.tpl"}
		$results = array();
{foreach from=$entity->getAttributes() item=attribute}
{if !$attribute->_cardinalityUpper || $attribute->_cardinalityUpper == 1}
		if (!$attr || ('{$attribute->_name}' == $attr && array_key_exists($attr, $this->_dirty))) {ldelim}
			$results['{$attribute->_name}'] ={if $attribute->_useReference}& {/if}$this->_dirty['{$attribute->_name}'];
		{rdelim}
{/if}
{if $attribute->getAggregateAttributes()}
   // mapped help content for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{if !$attr->_cardinalityUpper || $attr->_cardinalityUpper == 1}
		if ('{$attr->_name}' == $attr && $this->_{$attribute->_name} && $this->_{$attribute->_name}->isDirty('{$attr->_baseName}')) {ldelim}
			$results['{$attr->_name}'] = $this->_{$attribute->_name}->getChangedVals('{$attr->_baseName}');
		{rdelim}
{/if}
{/foreach}
{/if}
{/foreach}
{if $entity->_parentEntity}
		$results = array_merge($results, parent::getChangedVals($attr));
{/if}
    {include file="entity-aspect-after.tpl"}
		if ($attr) {ldelim}
			return $results[$attr];
		{rdelim}
		else {ldelim}
			return $results;
		{rdelim}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} getDefaultAttributeValue
	/**
	 * returns the default value for the attribute $attr IF a default value has 
	 * been configured for that attribute in the entity model (using the 'default'
   * xml attribute). returns NULL if no default value has been configured
	 * @param string $attr name of the attribute to return the default value for
	 * @return mixed
	 * @access public
	 */
	function getDefaultAttributeValue($attr) {ldelim}
    $default = NULL;
    {$Template->assign('aopMethodName', 'getDefaultAttributeValue')}
    {include file="entity-aspect-before.tpl"}
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_default !== $smarty.const.NULL}
    if (!isset($default) && '{$attribute->_name}' == $attr) {ldelim}
      $default = {$attribute->_default};
    {rdelim}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
		return $default;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} getOptionLabel
	/**
	 * returns the option label for the attribute and option value specified. if 
   * $value is not a valid option value, $value will be returned
	 * @param string $attr the name of the attribute
   * @param mixed $value the option value. if this is an array, the return value 
   * will be an associative array of labels indexed by these values
	 * @access public
   * @return string
	 */
	function getOptionLabel($attr, $value) {ldelim}
    if ($value && ($options =& $this->getOptionsMap($attr, TRUE)) && ((!is_array($value) && isset($options[$value])) || (is_array($value) && array_intersect($value, array_keys($options))))) {ldelim}
      $label = is_array($value) ? array() : $options[$value];
      if (is_array($value)) {ldelim}
        foreach($value as $key) {ldelim}
          $label[$key] = isset($options[$key]) ? $options[$key] : $key;
        {rdelim}
      {rdelim}
    {rdelim}
    else {ldelim}
      $label = $value;
    {rdelim}
    return $label;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// {ldelim}{ldelim}{ldelim} getOptionsMap
	/**
	 * Returns an associative array of all possible options for the specified 
	 * attribute. This method ONLY applies to attributes that utilize the 
	 * "depends=(option|options|range)" attribute in which case the var "options" or "min/max"  
	 * sub-element must specify the possible options for that attribute in the 
	 * format "[option1] [option2]..." or "[option1 label key]=[option1 value]..." 
	 * for options. This method may be invoked statically
	 * 
	 * @param string $attr the name of the attribute to return the options map for
   * @param boolean $convertLabels whether or not to convert the labels using this 
   * entity's resources
   * @param boolean $onlyEntityAttrs whether or not only this entity's current attribute 
   * values should be returned in the options map. this may be useful in the case where 
   * the resulting values will be used as a toggle switch between different attribute 
   * values where that attribute has a cardinality relationship with this entity
	 * @return associative array of value/label key values
	 * @access public
	 */
	function &getOptionsMap($attr, $convertLabels=FALSE, $onlyEntityAttrs=FALSE) {ldelim}
    $options = NULL;
    
    {$Template->assign('aopMethodName', "getOptionsMap")}
    {include file="entity-aspect-before.tpl"}
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->hasOptions()}
		if (!$options && '{$attribute->_name}' == $attr) {ldelim}
{if !$attribute->isEntity()}
{if $attribute->hasCodeOptions()}
			{$attribute->getVar('code')}
{elseif $attribute->hasRbOptions()}
			if (SRA_ResourceBundle::isValid($rb =& SRA_ResourceBundle::getBundle($this->getOptionsBundle($attr)))) {ldelim}
				$options = $rb->getData();
			{rdelim}
{elseif $attribute->hasSqlOptions()}
			$options = SRA_AttributeValidator::getSqlOptionsMap('{$attribute->getVar('sql')}');
{else}
			$options = array({foreach from=$attribute->getOptionsMap() key=label item=value}'{$value}' => '{$label}', {/foreach});
{/if}
{else}
{if $attribute->hasCodeOptions()}
			{$attribute->getVar('code')}
      $options = $options;
{else}
			$optionsMap = array();
      if (!$onlyEntityAttrs) {ldelim}
  			$dao =& SRA_DaoFactory::getDao('{$attribute->_type}');
        $options =& $dao->findBySqlConstraints(array(), {if $attribute->getVar('constraint')}'{$attribute->getVar('constraint')}'{else}FALSE{/if}, {if $attribute->getVar('order-by')}'{$attribute->getVar('order-by')}'{else}FALSE{/if}, {if $attribute->getVar('limit')}{$attribute->getVar('limit')}{else}FALSE{/if}, {if $attribute->getVar('offset')}{$attribute->getVar('offset')}{else}FALSE{/if});
      {rdelim}
      else {ldelim}
        $options =& $this->getAttribute($attr);
      {rdelim}
			if (is_array($options)) {ldelim}
				$keys = array_keys($options);
				foreach ($keys as $key) {ldelim}
					$optionsMap[$options[$key]->getPrimaryKey()] = $options[$key]->{$attribute->getOptionsValMethod()}('{$attribute->getVar('displ')}');
				{rdelim}
			{rdelim}
			$options = $optionsMap;
{/if}
{/if}
		{rdelim}
{elseif $attribute->hasRange()}
		if ('{$attribute->_name}' == $attr) {ldelim}
			$options = array({foreach from=$attribute->getRangeArray() item=value}'{$value}' => '{$value}', {/foreach});
		{rdelim}
{/if}
{if $attribute->getAggregateAttributes()}
    // mapped help content for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{if $attr->hasOptions()}
    if ('{$attr->_name}' == $attr) {ldelim}
      $obj =& $this->get{$attribute->getMethodName()}();
      if (!$obj) {ldelim}
        require_once('{$attribute->_type}{$entity->_voSuffix}.{$smarty.const.SRA_SYS_PHP_EXTENSION}');
        $obj = new {$attribute->_type}{$entity->_voSuffix}(); 
      {rdelim}
      $options = $obj->getOptionsMap('{$attr->_baseName}', $convertLabels, $onlyEntityAttrs);
    {rdelim}
{/if}
{/foreach}
{/if}
{/foreach}

    if ($options && $convertLabels) {ldelim}
      $resources =& {$className}::getEntityResources();
      $keys = array_keys($options);
      foreach ($keys as $key) {ldelim}
        $options[$key] = $resources->getString($options[$key]);
      {rdelim}
    {rdelim}
    
    {include file="entity-aspect-after.tpl"}
		return $options;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} getOptionsBundle
	/**
	 * Returns the path to the resource bundle representing all possible options 
   * for the specified attribute. This method ONLY applies to attributes that 
   * utilize the "depends=(option|options)" attribute where the nested "var" 
   * type is "resources" (the value of this var will be returned by this method) 
   * This method may be invoked statically.
	 * 
	 * @param string $attr the name of the attribute to return the resource bundle 
   * path for
	 * @return string
	 * @access public
	 */
	function getOptionsBundle($attr) {ldelim}
    {$Template->assign('aopMethodName', 'getOptionsBundle')}
    {include file="entity-aspect-before.tpl"}
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->hasOptions() && !$attribute->isEntity() && $attribute->hasRbOptions()}
		if ('{$attribute->_name}' == $attr) {ldelim}
      {include file="entity-aspect-after.tpl"}
			return '{$attribute->getVar('resources')}';
    {rdelim}
{/if}
{if $attribute->getAggregateAttributes()}
    // mapped help content for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{if $attr->hasOptions() && !$attr->isEntity() && $attr->hasRbOptions()}
		if ('{$attr->_name}' == $attr) {ldelim}
      {include file="entity-aspect-after.tpl"}
			return '{$attr->getVar('resources')}';
    {rdelim}
{/if}
{/foreach}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
		return NULL;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// {ldelim}{ldelim}{ldelim} getRemovedVals
	/**
	 * Returns an array containing all of the values that have been removed for a 
	 * given array attribute. if the attribute specified is not an array, or if 
	 * no values have been added, FALSE will be returned
	 * 
	 * @param string $attr the name of the attribute to return the values that 
	 * have been removed for
	 * @return array
	 * @access public
	 */
	function &getRemovedVals($attr) {ldelim}
    {$Template->assign('aopMethodName', "getRemovedVals")}
    {include file="entity-aspect-before.tpl"}
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_cardinality || ($attribute->isEntity() && $attribute->_onRemoveDelete)}
		if ('{$attribute->_name}' == $attr && array_key_exists($attr, $this->_dirty) && array_key_exists(SRA_ATTRIBUTE_REMOVE_DIRTY_KEY, $this->_dirty[$attr])) {ldelim}
      {include file="entity-aspect-after.tpl"}
			return $this->_dirty[$attr][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY];
		{rdelim}
{/if}

{if $attribute->getAggregateAttributes()}
   // mapped help content for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{if $attr->_cardinality}
		if ('{$attr->_name}' == $attr && $this->_{$attribute->_name} && $this->_{$attribute->_name}->isDirty('{$attr->_baseName}')) {ldelim}
      {include file="entity-aspect-after.tpl"}
			return $this->_{$attribute->_name}->getRemovedVals('{$attr->_baseName}');
		{rdelim}
{/if}
{/foreach}
{/if}

{/foreach}
    {include file="entity-aspect-after.tpl"}
{if $entity->_parentEntity}
		return parent::getRemovedVals($attr);
{else}
		return FALSE;
{/if}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}


	// {ldelim}{ldelim}{ldelim} isDirty
	/**
	 * Returns TRUE if this value object or a value object attribute has been 
	 * modified since it was originally initialized. 
	 * 
	 * @param mixed $attr the name of the attribute to check. if not specified, 
	 * then this method will return TRUE if ANY of its attributes have been 
	 * modified. if this is an array, TRUE will be returned if any of the 
	 * attributes in that array are dirty
	 * @param boolean $baseAttrsOnly whether or not only base attributes should 
	 * be considered. base attributes are attributes stored in the base table for 
	 * the entity. if this param is TRUE, then the $attr param will be ignored
{if $entity->_parentEntity}
	 * @param boolean $ignoreParent whether or not to call up to the parent 
	 * isDirty method
{/if}
	 * @return boolean
	 * @access public
	 */
	function isDirty($attr = FALSE, $baseAttrsOnly = FALSE{if $entity->_parentEntity}, $ignoreParent = FALSE{/if}) {ldelim}
    {$Template->assign('aopMethodName', "isDirty")}
    {include file="entity-aspect-before.tpl"}
		if ($baseAttrsOnly) {ldelim}
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->isBaseAttribute() && !$attribute->getMappedAttributes()}
			if ($this->isDirty('{$attribute->_name}')) {ldelim}
				$ret = TRUE;
			{rdelim}
{elseif $attribute->getMappedAttributes()}
      // mapped attributes of {$attribute->_name}
      if (($nattr ={if $attribute->_useReference}&{/if} $this->get{$attribute->getMethodName()}()) && $nattr->isDirty(array({foreach from=$attribute->getMappedAttributes() item=attr}'{$attr->_baseName}', {/foreach}), TRUE{if $entity->_parentEntity}, $ignoreParent{/if})) {ldelim}
        $ret = TRUE;
      {rdelim}
{/if}
{/foreach}
{if $entity->_parentEntity}
      {include file="entity-aspect-after.tpl"}
			if (!$ignoreParent) {ldelim}
				$ret = parent::isDirty($attr, $baseAttrsOnly);
			{rdelim}
			else {ldelim}
				$ret = FALSE;
			{rdelim}
{else}
			$ret = FALSE;
{/if}
		{rdelim}
		else {ldelim}
			$attr = !$attr || is_array($attr) ? $attr : array($attr);
			if ($attr && count($attr)) {ldelim}
				foreach($attr as $a) {ldelim}
					if (isset($this->_dirty[$a])) {ldelim}
						$ret = TRUE;
            break;
					{rdelim}
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->getAggregateAttributes()}
          // mapped attributes for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{if !$attr->_readOnly}
          else if (('{$attribute->_name}_{$attr->_name}' == $a || '{$attr->_name}' == $a) && ($nattr ={if $attribute->_useReference}&{/if} $this->get{$attribute->getMethodName()}())) {ldelim}
            if ($ret = $nattr->isDirty('{$attr->_baseName}', $baseAttrsOnly{if $entity->_parentEntity}, $ignoreParent{/if})) {ldelim} break; {rdelim}
          {rdelim}
{/if}
{/foreach}
{elseif $attribute->isEntity() && !$attribute->_readOnly}
          else if (($a == '{$attribute->_name}' || SRA_Util::beginsWith($a, '{$attribute->_name}_')) && ($nattr ={if $attribute->_useReference}&{/if} $this->get{$attribute->getMethodName()}()){if !$attribute->_cardinality} && $nattr->isDirty($a == '{$attribute->_name}' ? NULL : substr($a, strlen('{$attribute->_name}_'))){/if}) {ldelim}
{if $attribute->_cardinality}
            foreach(array_keys($nattr) as $nkey) {ldelim}
              if ($nattr[$nkey]->isDirty($a == '{$attribute->_name}' ? NULL : substr($a, strlen('{$attribute->_name}_')))) {ldelim}
                $ret = TRUE;
                break;
              {rdelim}
            {rdelim}
            if ($ret) break;
{else}
						$ret = TRUE;
            break;
{/if}
          {rdelim}
{/if}
{/foreach}
				{rdelim}
        {include file="entity-aspect-after.tpl"}
				return $ret;
			{rdelim}
			else {ldelim}
				$ret = count($this->_dirty) > 0;
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->getMappedAttributes()}
        if (!$ret && ($nattr ={if $attribute->_useReference}&{/if} $this->get{$attribute->getMethodName()}()) && $nattr->isDirty($attr, $baseAttrsOnly)) {ldelim}
          $ret = TRUE;
        {rdelim}
{/if}
{/foreach}
			{rdelim}
		{rdelim}
    {include file="entity-aspect-after.tpl"}
    return $ret;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// {ldelim}{ldelim}{ldelim} hasBeenSet
	/**
	 * Returns TRUE if the attribute specified has been set using a "set" or "add" 
	 * method
	 * 
	 * @param string $attr the name of the attribute to check
	 * @return boolean
	 * @access public
	 */
	function hasBeenSet($attr) {ldelim}
    {$Template->assign('aopMethodName', "hasBeenSet")}
    {include file="entity-aspect-before.tpl"}
{assign var="started" value="0"}
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->getAggregateAttributes()}
    // mapped attributes for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{if !$attr->_readOnly}
    {if $started}else {/if}if ('{$attr->_name}' == $attr && ($nattr ={if $attribute->_useReference}&{/if} $this->get{$attribute->getMethodName()}())) {ldelim}
      $ret = $nattr->hasBeenSet('{$attr->_baseName}');
    {rdelim}
{assign var="started" value="1"}
{/if}
{/foreach}
{/if}
{/foreach}
		$ret = $ret ? $ret : isset($this->_setAttrs[$attr]);
    {include file="entity-aspect-after.tpl"}
    return $ret;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// {ldelim}{ldelim}{ldelim} getEntityFiles
	/**
	 * returns an array of all of the file attributes for this entity indexed on 
	 * the attribute name
	 * @return SRA_FileAttribute[]
	 * @access public
	 */
	function &getEntityFiles() {ldelim}
    {$Template->assign('aopMethodName', "getFiles")}
    {include file="entity-aspect-before.tpl"}
		$files = array();
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_isFile}
		$files['{$attribute->_name}'] =& $this->get{$attribute->getMethodName()}();
{/if}
{if $attribute->getAggregateAttributes()}
    // mapped attributes for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{if $attr->_isFile}
		$files['{$attr->_name}'] =& $this->get{$attr->getMethodName()}();
{/if}
{/foreach}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
		return $files;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	

	// {ldelim}{ldelim}{ldelim} getGlobalGetMethod
	/**
	 * returns the getter method name for a given global identifier or FALSE if 
	 * this value object does not contain that global attribute
	 * 
	 * @param string $globalId the global name 
	 * @return void
	 * @access public
	 */
	function getGlobalGetMethod($globalId) {ldelim}
    {$Template->assign('aopMethodName', "getGlobalGetMethod")}
    {include file="entity-aspect-before.tpl"}
{assign var="started" value="0"}
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_globalName}
		{if $started}else {/if}if ('{$attribute->_globalName}' == $globalId) {ldelim}
			$ret = 'get{$attribute->getMethodName()}';
		{rdelim}
    {assign var="started" value="1"}
{/if}
{if $attribute->getAggregateAttributes()}
    // mapped attributes for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{if $attr->_globalName}
		{if $started}else {/if}if ('{$attr->_globalName}' == $globalId) {ldelim}
			$ret = 'get{$attr->getMethodName()}';
		{rdelim}
    {assign var="started" value="1"}
{/if}
{/foreach}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
		return $ret ? $ret : FALSE;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// {ldelim}{ldelim}{ldelim} mergeGlobals
	/**
	 * This method is used to merge common global attributes in other value 
	 * object in this one. Only attributes that are not already set in this 
	 * object will be set
	 * 
	 * @param ValueObject[] $entities an array of or single value object to merge 
	 * the common global attributes with
	 * @return void
	 * @access public
	 */
	function mergeGlobals(& $entities) {ldelim}
    {$Template->assign('aopMethodName', "mergeGlobals")}
    {include file="entity-aspect-before.tpl"}
		if (!is_array($entities)) {ldelim}
			$globalEntities = array($entities);
		{rdelim}
    else {ldelim}
      $globalEntities =& $entities;
    {rdelim}
		$keys = array_keys($globalEntities);
		foreach ($keys as $key) {ldelim}
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_globalName}
			if (!$this->get{$attribute->getMethodName()}() && ($methodName = $globalEntities[$key]->getGlobalGetMethod('{$attribute->_globalName}'))) {ldelim}
        $val ={if $attribute->_useReference}& {/if}$globalEntities[$key]->${ldelim}methodName{rdelim}();
{if $attribute->_isFile}
        if (SRA_FileAttribute::isValid($val)) {ldelim}
          $val->_setAttribute('{$attribute->_name}');
          $val->_setEntity('{$entity->_name}');
          $val->_setEntityId($this->getPrimaryKey());
        {rdelim}
{/if}
				$this->set{$attribute->getMethodName()}($val);
			{rdelim}
{/if}
{if $attribute->getAggregateAttributes()}
    // mapped attributes for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{if $attr->_globalName}
			if (!$this->get{$attr->getMethodName()}() && ($methodName = $globalEntities[$key]->getGlobalGetMethod('{$attr->_globalName}'))) {ldelim}
        $val ={if $attr->_useReference}& {/if}$globalEntities[$key]->${ldelim}methodName{rdelim}();
{if $attr->_isFile}
        if (SRA_FileAttribute::isValid($val)) {ldelim}
          $val->_setAttribute('{$attr->_name}');
          $val->_setEntity('{$entity->_name}');
          $val->_setEntityId($this->getPrimaryKey());
        {rdelim}
{/if}
				$this->set{$attr->getMethodName()}($val);
			{rdelim}
{/if}
{/foreach}
{/if}

{/foreach}
		{rdelim}
    {include file="entity-aspect-after.tpl"}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// {ldelim}{ldelim}{ldelim} render
	/**
	 * Renders this entity using a view template configured for this entity. Views 
	 * are configured for an entity using the "entity" "view" sub-element. For 
	 * more information, see the entity-model dtd documentation
	 * 
	 * @param String $viewKey the identifier of the view to render. if not 
	 * specified then the default view will be rendered. If invalid, an SRA_Error 
	 * object will be returned. if the $viewKey is 'xml' (not case sensitive), an 
   * xml representation of this {$entity->_name} instance will be rendered. if 
   * it is "json", a json representation of the entity will be output
	 * @param array $attributes if "renderAttributes" is true for the view and 
	 * this parameter is specified, then only the attributes in it will be 
	 * rendered
	 * @param array $skipAttributes if "renderAttributes" is true, these 
	 * attributes will not be rendered
	 * @param array $viewLabels if "renderAttributes" is true, these labels, if 
	 * specified, will override the default labels for the corresponding entities 
	 * and attributes
	 * @param array $viewValues if "renderAttributes" is true, these values, if 
	 * specified, will override the default values for the corresponding attributes
	 * @param boolean $skipLookup if the view uses a SRA_LookupProcessor, specifies 
	 * rather or not the lookup has already been performed
   * @param boolean $suppressHeaders whether or not to suppress any view related 
   * "header" output
   * @access public
	 * @return void on success or SRA_Error object otherwises
	 */
	function render($viewKey = FALSE, $attributes = FALSE, $skipAttributes = FALSE, $viewLabels = FALSE, $viewValues = FALSE, $skipLookup = FALSE, $suppressHeaders=FALSE) {ldelim}
    {$Template->assign('aopMethodName', "render")}
    {include file="entity-aspect-before.tpl"}
		static $lp;
    
    // render xml
    if (strtolower($viewKey) == 'xml') {ldelim}
      if (!$suppressHeaders) {ldelim} header('Content-type: text/xml'); {rdelim}
      $this->renderXml();
      return;
    {rdelim}
    // render json
    else if (strtolower($viewKey) == 'json') {ldelim}
      echo $this->toJson($attributes, $skipAttributes);
      return;
    {rdelim}
		
		$tpl =& SRA_Controller::getAppTemplate();
		$rb =& {$className}::getEntityResources();
		$tpl->assign('entityName', '{$entity->_name}');
		$tpl->assign('attrs', FALSE);
{foreach from=$entity->_views item=view}
		if ($viewKey == '{$view->_id}'{if $view->_default} || !$viewKey{/if}) {ldelim}
      $tpl->assign('viewName', '{$view->_id}');
			$params = new SRA_Params(array({foreach from=$view->_params->_params key=key item=param}{if $param.type neq $smarty.const.SRA_ENTITY_MODELER_VIEW_RESOURCES_PARAM_TYPE}'{$key}' => array('id' => '{$param.id}', {if $param.type}'type' => '{$param.type}', {/if}'value' => $this->parseString('{$Template->strReplace("'", "\\'", $param.value)}', TRUE)), {/if}{/foreach}));
{if $view->_lookupProcessor}
			// SRA_LookupProcessor used to access entities to render
			if (!$skipLookup) {ldelim}
				include_once('{$view->_lookupProcessor}');
				$lp = new {$view->_lookupProcessorClass}($params, '{$entity->_name}');
				$entities =& $lp->lookup();
				// if {$view->_lookupProcessorClass} returns value other than array, return (no rendering necessary)
				if (!is_array($entities)) {ldelim}
          {include file="entity-aspect-after.tpl"}
					return;
				{rdelim}
				$tpl->assignByRef('params', $params);
{if $view->_lpNoResultsTpl}
				if (!is_array($entities) || !count($entities)) {ldelim}
					$tpl->display('{$view->_lpNoResultsTpl}');
          {include file="entity-aspect-after.tpl"}
					return;
				{rdelim}
{/if}
{if $view->_lpNoResultsMsg}
				if (!is_array($entities) || !count($entities)) {ldelim}
					print($rb->getString('{$view->_lpNoResultsMsg}'));
          {include file="entity-aspect-after.tpl"}
					return;
				{rdelim}
{/if}
				$lp->renderHeader();
				if (is_array($entities)) {ldelim}
					$keys = array_keys($entities);
					foreach ($keys as $key) {ldelim}
{if $view->getLabel($entity->_name)}
						$tpl->assign('entityLabel', $rb->getString('{$view->getLabel($entity->_name)}'));
{else}
						$tpl->assign('entityLabel', $entities[$key]->getEntityLabel());
{/if}
						if (is_array($viewLabels) && $viewLabels['{$entity->_name}']) {ldelim}
							$tpl->assign('entityLabel', $rb->getString($viewLabels['{$entity->_name}']));
						{rdelim}
						$tpl->assignByRef('{$view->_templateVar}', $entities[$key]);
						$lp->renderEntityPrefix($this);
						$entities[$key]->render($viewKey, $attributes, $skipAttributes, $viewLabels, $viewValues, TRUE);
						$tpl->assignByRef('params', $params);
						$lp->renderEntityPostfix($this);
					{rdelim}
				{rdelim}
				$lp->renderFooter();
        {include file="entity-aspect-after.tpl"}
				return;
			{rdelim}
{/if}
{if $view->_viewLabels}
			$viewLabels = array({foreach from=$view->_viewLabels key=attr item=label}'{$attr}' => '{$label}', {/foreach});
{/if}
{if $view->_viewValues}
			$viewValues = array({foreach from=$view->_viewValues key=attr item=val}'{$attr}' => {$val}, {/foreach});
{/if}
{if $view->getLabel($entity->_name)}
			$tpl->assign('entityLabel', $rb->getString('{$view->getLabel($entity->_name)}'));
{else}
			$tpl->assign('entityLabel', $this->getEntityLabel());
{/if}
			if (is_array($viewLabels) && $viewLabels['{$entity->_name}']) {ldelim}
				$tpl->assign('entityLabel', $rb->getString($viewLabels['{$entity->_name}']));
			{rdelim}
			$tpl->assignByRef('{$view->_templateVar}', $this);
			$tpl->assignByRef('params', $params);
{if !$view->hasViewProcessors()}
{foreach from=$view->_viewHeaders item=header}
			if (!$suppressHeaders) {ldelim} header($this->parseString('{$header->_str}'), {if $header->_replace}TRUE{else}FALSE{/if}{if $header->_responseCode}, {$header->_responseCode}{/if}); {rdelim}
{/foreach}
{else}
			ob_start();
{/if}

      $viewResources = array();
{* add view resources *}
{foreach from=$view->_params->_params key=key item=param}
{if $param.type eq $smarty.const.SRA_ENTITY_MODELER_VIEW_RESOURCES_PARAM_TYPE}
      $viewResources['{$param.id}'] =& SRA_ResourceBundle::getBundle('{$param.value}');
{/if}
{/foreach}

{if $view->_template|lower neq 'xml' && $view->_template|lower neq 'json'}
      $vkeys = array_keys($viewResources);
      foreach($vkeys as $vkey) {ldelim}
        $tpl->assignByRef($vkey, $viewResources[$vkey]);
      {rdelim}
{if $view->_renderAttributes}
      $attrs = {if $view->_attributesCode}{$view->_attributesCode}{else}array({if $view->getAttributes()}{foreach from=$view->getAttributes() item=attr}'{$attr}', {/foreach}{else}{foreach from=$entity->getAttributes() item=attr}'{$attr->_name}', {/foreach}{/if}){/if};
			$tpl->assignByRef('attrs', $attrs);
{/if}
{if $view->_pre}
      echo '{$view->_pre}';
{/if}
{if $view->_preTemplate}
			$tpl->display('{$view->_preTemplate}');
{/if}
{if $view->_template}
			$tpl->display('{$view->_template}');
{/if}
{if $view->_renderAttributes}
			if (!is_array($attributes)) {ldelim}
				$attributes = {if $view->_attributesCode}{$view->_attributesCode}{else}array({if $view->getAttributes()}{foreach from=$view->getAttributes() item=attr}'{$attr}', {/foreach}{else}{foreach from=$entity->getAttributes() item=attr}'{$attr->_name}', {/foreach}{/if}){/if};
			{rdelim}
			if (!is_array($skipAttributes)) {ldelim}
				$skipAttributes = array({foreach from=$view->_skipAttributes item=attr}'{$attr}', {/foreach});
			{rdelim}
			$keys = array_keys($attributes);
			foreach ($keys as $key) {ldelim}
				if (in_array($attributes[$key], $skipAttributes)) {ldelim}
					unset($attributes[$key]);
				{rdelim}
			{rdelim}
			$keys = array_keys($attributes);
			foreach ($keys as $key) {ldelim}
				$attrVal =& $this->getAttribute($attributes[$key]);
{if $view->_lookupProcessor}
				$lp->renderAttributePrefix($this, $attrVal, $attributes[$key]);
{/if}
				$this->renderAttribute($attributes[$key], {if !$view->_forwardView}$viewKey{else}'{$view->_forwardView}'{/if}, FALSE, FALSE, $viewLabels, $viewValues);
				$tpl->assignByRef('{$view->_templateVar}', $this);
				$tpl->assign('entityName', '{$entity->_name}');
{if $view->getLabel($entity->_name)}
				$tpl->assign('entityLabel', $rb->getString('{$view->getLabel($entity->_name)}'));
{else}
				$tpl->assign('entityLabel', $this->getEntityLabel());
{/if}
				if (is_array($viewLabels) && $viewLabels['{$entity->_name}']) {ldelim}
					$tpl->assign('entityLabel', $rb->getString($viewLabels['{$entity->_name}']));
				{rdelim}
{if $view->_lookupProcessor}
				$lp->renderAttributePostfix($this, $attrVal, $attributes[$key]);
{/if}
			{rdelim}
{/if}
{if $entity->_parentEntity}
			parent::render($viewKey, $attributes, $skipAttributes, $viewLabels, $viewValues);
{/if}
{if $view->_postTemplate}
			$tpl->display('{$view->_postTemplate}');
{/if}
{if $view->_post}
      echo '{$view->_post}';
{/if}

{* xml output *}
{elseif $view->_template|lower eq 'xml'}
      $this->renderXml({if $view->_attributes}array({foreach from=$view->_attributes item=attr}'{$attr}', {/foreach}){else}FALSE{/if}, {if $view->_skipAttributes}array({foreach from=$view->_skipAttributes item=attr}'{$attr}', {/foreach}){else}FALSE{/if}, $viewResources);
{* json output *}
{elseif $view->_template|lower eq 'json'}
      echo $this->toJson({if $view->_attributes}array({foreach from=$view->_attributes item=attr}'{$attr}', {/foreach}){else}FALSE{/if}, {if $view->_skipAttributes}array({foreach from=$view->_skipAttributes item=attr}'{$attr}', {/foreach}){else}FALSE{/if}, $viewResources);
{/if}
{if $view->hasViewProcessors()}
			$buffer = ob_get_contents();
			ob_end_clean();
			$randomFiles = array();
			$tempFiles = array();
{foreach from=$view->_viewProcessors item=viewProcessor}
{if $viewProcessor->_preProcessCmd}
			// execute pre-processor program
			$preCmd = trim('{$viewProcessor->_preProcessCmd}');
			if (strpos($preCmd, '{ldelim}$outputFile{rdelim}') !== FALSE) {ldelim}
				if (!$outputFile) {ldelim}
					$outputFile = SRA_File::createRandomFile();
					$tempFiles[] = $outputFile;
					$fp = fopen($outputFile, 'w');
					fwrite($fp, $buffer);
					fclose($fp);
				{rdelim}
				$preCmd = str_replace('{ldelim}$outputFile{rdelim}', $outputFile, $preCmd);
			{rdelim}
			if (strpos($preCmd, '{ldelim}$randomFile{rdelim}') !== FALSE) {ldelim}
				if (!isset($randomFiles[0])) {ldelim}
					$randomFiles[0] = SRA_File::createRandomFile();
				{rdelim}
				$preCmd = str_replace('{ldelim}$randomFile{rdelim}', $randomFiles[0], $preCmd);
			{rdelim}
			for($i=1; $i<=10; $i++) {ldelim}
				if (strpos($preCmd, '{ldelim}$randomFile' . $i . '{rdelim}') !== FALSE) {ldelim}
					if (!isset($randomFiles[$i])) {ldelim}
						$randomFiles[$i] = SRA_File::createRandomFile();
					{rdelim}
					$args = str_replace('{ldelim}$randomFile' . $i . '{rdelim}', $randomFiles[$i], $preCmd);
				{rdelim}
			{rdelim}
			$preCmd = str_replace('{ldelim}LENGTH{rdelim}', strlen($buffer), $preCmd);
			$preCmd = $this->parseString($preCmd);
			$tmp = exec($preCmd);
{/if}
			// execute processor program and get output
			$args = trim('{$viewProcessor->_args}');
			if ($args) {ldelim}
				if (strpos($args, '{ldelim}$outputFile{rdelim}') !== FALSE) {ldelim}
					$outputFile = SRA_File::createRandomFile();
					$tempFiles[] = $outputFile;
					$fp = fopen($outputFile, 'w');
					fwrite($fp, $buffer);
					fclose($fp);
					$args = str_replace('{ldelim}$outputFile{rdelim}', $outputFile, $args);
				{rdelim}
				if (strpos($args, '{ldelim}$randomFile{rdelim}') !== FALSE) {ldelim}
					if (!isset($randomFiles[0])) {ldelim}
						$randomFiles[0] = SRA_File::createRandomFile();
					{rdelim}
					$args = str_replace('{ldelim}$randomFile{rdelim}', $randomFiles[0], $args);
				{rdelim}
				for($i=1; $i<=10; $i++) {ldelim}
					if (strpos($args, '{ldelim}$randomFile' . $i . '{rdelim}') !== FALSE) {ldelim}
						if (!isset($randomFiles[$i])) {ldelim}
							$randomFiles[$i] = SRA_File::createRandomFile();
						{rdelim}
						$args = str_replace('{ldelim}$randomFile' . $i . '{rdelim}', $randomFiles[$i], $args);
					{rdelim}
				{rdelim}
				$args = str_replace('{ldelim}LENGTH{rdelim}', strlen($buffer), $args);
        $argParams =& $params->getParams();
        $akeys = array_keys($argParams);
        foreach($akeys as $akey) {ldelim}
          $args = str_replace('{ldelim}$' . $akey . '{rdelim}', $argParams[$akey], $args);
        {rdelim}
        $args = str_replace('{ldelim}SRA_DIR{rdelim}', SRA_DIR, str_replace('{ldelim}APP_DIR{rdelim}', SRA_Controller::getAppDir(), $args));
				$args = $this->parseString($args);
			{rdelim}
			$descriptorspec = array(
				 0 => array('pipe', 'r'),
				 1 => array('pipe', 'w'),
				 2 => array('file', SRA_Controller::getAppTmpDir() . '/.{$className}-{$viewProcessor->_id}-errors', 'a')
			);
			$process = proc_open("{$viewProcessor->_path} " . $args, $descriptorspec, $pipes);
{if $viewProcessor->_inputView}
      if (!is_file($outputFile)) {ldelim}
			  // input buffer into STDIN
        fwrite($pipes[0], $buffer);
      {rdelim}
{/if}
			fclose($pipes[0]);
      $bufferLength = strlen($buffer);
{if $viewProcessor->_outputFilePath}
			// get output from file
			fclose($pipes[1]);
			proc_close($process);
			$resultsFile = trim('{$viewProcessor->_outputFilePath}');
			if (strpos($resultsFile, '{ldelim}$randomFile{rdelim}') !== FALSE) {ldelim}
				$resultsFile = str_replace('{ldelim}$randomFile{rdelim}', $randomFiles[0], $resultsFile);
			{rdelim}
			for($i=1; $i<=10; $i++) {ldelim}
				if (strpos($resultsFile, '{ldelim}$randomFile' . $i . '{rdelim}') !== FALSE) {ldelim}
					$resultsFile = str_replace('{ldelim}$randomFile' . $i . '{rdelim}', $randomFiles[$i], $resultsFile);
				{rdelim}
			{rdelim}
			$resultsFile = str_replace('{ldelim}LENGTH{rdelim}', $bufferLength, $resultsFile);
			$resultsFile = $this->parseString($resultsFile);
			$newBuffer =& SRA_File::toString($resultsFile);
			unlink($resultsFile);
{else}
			// get output from STDOUT
			$newBuffer = '';
			while(!feof($pipes[1]) && fread($pipes[1], 1) != "\n") {ldelim}{rdelim}
			while(!feof($pipes[1])) {ldelim}
				 $newBuffer .= fread($pipes[1], 4096);
			{rdelim}
			fclose($pipes[1]);
			proc_close($process);
{/if}
{if $viewProcessor->_postProcessCmd}
			// execute post-processor program
			$postCmd = trim('{$viewProcessor->_postProcessCmd}');
			if (strpos($postCmd, '{ldelim}$outputFile{rdelim}') !== FALSE) {ldelim}
				if (!$outputFile) {ldelim}
					$outputFile = SRA_File::createRandomFile();
					$tempFiles[] = $outputFile;
					$fp = fopen($outputFile, 'w');
					fwrite($fp, $buffer);
					fclose($fp);
				{rdelim}
				$postCmd = str_replace('{ldelim}$outputFile{rdelim}', $outputFile, $postCmd);
			{rdelim}
			if (strpos($postCmd, '{ldelim}$randomFile{rdelim}') !== FALSE) {ldelim}
				if (!isset($randomFiles[0])) {ldelim}
					$randomFiles[0] = SRA_File::createRandomFile();
				{rdelim}
				$postCmd = str_replace('{ldelim}$randomFile{rdelim}', $randomFiles[0], $postCmd);
			{rdelim}
			for($i=1; $i<=10; $i++) {ldelim}
				if (strpos($postCmd, '{ldelim}$randomFile' . $i . '{rdelim}') !== FALSE) {ldelim}
					if (!isset($randomFiles[$i])) {ldelim}
						$randomFiles[$i] = SRA_File::createRandomFile();
					{rdelim}
					$args = str_replace('{ldelim}$randomFile' . $i . '{rdelim}', $randomFiles[$i], $postCmd);
				{rdelim}
			{rdelim}
			$postCmd = str_replace('{ldelim}LENGTH{rdelim}', $bufferLength, $postCmd);
			$postCmd = $this->parseString($postCmd);
			$tmp = exec($postCmd);
{/if}
			if (is_file($outputFile)) {ldelim} unlink($outputFile); $outputFile = NULL; {rdelim}
			$buffer = $newBuffer;
{/foreach}
			foreach ($randomFiles as $file) {ldelim}
				unlink($file);
			{rdelim}
			foreach ($tempFiles as $file) {ldelim}
				unlink($file);
			{rdelim}
{foreach from=$view->_viewHeaders item=header}
			if (!$suppressHeaders) {ldelim} header(str_replace('{ldelim}LENGTH{rdelim}', $bufferLength, $this->parseString('{$header->_str}')), {if $header->_replace}TRUE{else}FALSE{/if}{if $header->_responseCode}, {$header->_responseCode}{/if}); {rdelim}
{/foreach}
			echo $buffer;
{/if}
      {include file="entity-aspect-after.tpl"}
			return;
		{rdelim}
{/foreach}
    {include file="entity-aspect-after.tpl"}
		// view not found
		$msg = "{$className}::render: Failed - View '$viewKey' is not valid for this entity";
		return SRA_Error::logError($msg, __FILE__, __LINE__);
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// {ldelim}{ldelim}{ldelim} renderAttribute
	/**
	 * Renders an individual attribute
	 * 
	 * @param String $attribute the name of the attribute
	 * @param String $viewKey the identifier of the view to render. if not 
	 * specified then the default view will be rendered. If invalid, nothing will 
	 * be rendered
	 * @param array $attributes if "renderAttributes" is true for the view and 
	 * this parameter is specified, then only the attributes in it will be 
	 * rendered. only applies to attributes that reference an entity
	 * @param array $skipAttributes if "renderAttributes" is true, these 
	 * attributes will not be rendered. only applies to attributes that reference 
	 * @param array $viewLabels if "renderAttributes" is true, these labels, if 
	 * specified, will override the default labels for the corresponding entities 
	 * and attributes
	 * @param array $viewValues if "renderAttributes" is true, these values, if 
	 * specified, will override the default values for the corresponding attributes
	 * an entity
	 * @return void
	 * @access public
	 */
	function renderAttribute($attribute, $viewKey = FALSE, $attributes = FALSE, $skipAttributes = FALSE, $viewLabels = FALSE, $viewValues = FALSE) {ldelim}
    {$Template->assign('aopMethodName', "renderAttribute")}
    {include file="entity-aspect-before.tpl"}
    
		global $renderAttribute_nestedAttributes;
		global $renderAttribute_nestedAttributeLabels;
    
		if (!$renderAttribute_nestedAttributes) {ldelim}
			$renderAttribute_nestedAttributes = array();
			$renderAttribute_nestedAttributeLabels = array();
		{rdelim}
		
		$tpl =& SRA_Controller::getAppTemplate();
		$rb =& {$className}::getEntityResources();
		$fieldName = '';
		foreach($renderAttribute_nestedAttributes as $nestedName) {ldelim}
			$fieldName .= $nestedName . '_';
		{rdelim}
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_views}
		if ('{$attribute->_name}' == $attribute) {ldelim}
			$this->_renderAttributeName = '{$attribute->_name}';
			${$attribute->_name}Attributes = array();
			${$attribute->_name}SkipAttributes = array();
			${$attribute->_name}Labels = array();
{assign var='renderAttributes' value=0}
{foreach from=$attribute->_views item=view}
{if $view->_renderAttributes}{assign var='renderAttributes' value=1}{/if}
			if ($viewKey == '{$view->_id}'{if $view->_default} || !$viewKey{/if}) {ldelim}
        $tpl->assign('viewName', '{$view->_id}');
{if $view->_viewLabels}
				$viewLabels = array({foreach from=$view->_viewLabels key=attr item=label}'{$attr}' => '{$label}', {/foreach});
{/if}
{if $view->_viewValues}
				$viewValues = array({foreach from=$view->_viewValues key=attr item=val}'{$attr}' => {$val}, {/foreach});
{/if}
				$val =& $this->getAttribute($attribute);
				if ((!$val{if $attribute->_default} || ($val == $this->getDefaultAttributeValue('{$attribute->_name}') && !$this->_dirty['{$attribute->_name}']){/if}) && is_array($viewValues) && isset($viewValues['{$attribute->_name}'])) {ldelim}
					$val = $viewValues['{$attribute->_name}'];
				{rdelim}
{if $view->getValue($attribute->_name)}
				if (!$val{if $attribute->_default} || ($val == $this->getDefaultAttributeValue('{$attribute->_name}') && !$this->_dirty['{$attribute->_name}']){/if}) {ldelim}
					$val = {$view->getValue($attribute->_name)};
				{rdelim}
{/if}
				$tpl->assignByRef('{$smarty.const.ENTITY_VIEW_TEMPLATE_VAR_NAME}', $this);
				$tpl->assign{if $attribute->_useReference}ByRef{/if}('{$view->_templateVar}', $val);
				$fieldName .= '{$attribute->_name}';
				$tpl->assign('entityName', '{$entity->_name}');
				$tpl->assign('attributeName', '{$attribute->_name}');
        $tpl->assign('attributeType', '{$attribute->_type}');
				$tpl->assign('fieldName', {if $view->_fieldName}'{$view->_fieldName}'{else}SRA_EntityView::getGlobalFieldNamePrefix() . $fieldName . SRA_EntityView::getGlobalFieldNamePostfix(){/if});
				$tpl->assign('params', new SRA_Params(array({foreach from=$view->_params->_params key=key item=p}'{$key}' => array('id' => '{$p.id}', {if $p.type}'type' => '{$p.type}', {/if}'value' => $this->parseString('{$Template->strReplace("'", "\\'", $p.value)}', TRUE)), {/foreach})));
{if $view->getLabel($attribute->_name)}
				$tpl->assign('attributeLabel', $rb->getString('{$view->getLabel($attribute->_name)}'));
				${$attribute->_name}Labels['{$view->_id}'] = $rb->getString('{$view->getLabel($attribute->_name)}');
{else}
				$tpl->assign('attributeLabel', $this->getEntityLabel('{$attribute->_name}'));
				${$attribute->_name}Labels['{$view->_id}'] = $this->getEntityLabel('{$attribute->_name}');
{/if}
				if (is_array($viewLabels) && $viewLabels['{$attribute->_name}']) {ldelim}
					$tpl->assign('attributeLabel', $rb->getString($viewLabels['{$attribute->_name}']));
					${$attribute->_name}Labels['{$view->_id}'] = $viewLabels['{$attribute->_name}'];
				{rdelim}
{if $attribute->isEntity() && $view->_renderAttributes}
        $attrs = {if $view->_attributesCode}{$view->_attributesCode}{else}array({if $view->getAttributes()}{foreach from=$view->getAttributes() item=attr}'{$attr}', {/foreach}{else}{foreach from=$entity->getAttributes() item=attr}'{$attr->_name}', {/foreach}{/if}){/if};
				$tpl->assignByRef('attrs', $attrs);
				if (!is_array($attributes)) {ldelim}
					${$attribute->_name}Attributes['{$view->_id}'] = {if $view->_attributesCode}{$view->_attributesCode}{else}{if $view->getAttributes()}array({foreach from=$view->getAttributes() item=attr}'{$attr}', {/foreach}){else}FALSE{/if}{/if};
				{rdelim}
				else {ldelim}
					${$attribute->_name}Attributes['{$view->_id}'] = $attributes;
				{rdelim}
				if (!is_array($skipAttributes)) {ldelim}
					${$attribute->_name}SkipAttributes['{$view->_id}'] = {if $view->_skipAttributes}array({foreach from=$view->_skipAttributes item=attr}'{$attr}', {/foreach}){else}FALSE{/if};
				{rdelim}
				else {ldelim}
					${$attribute->_name}SkipAttributes['{$view->_id}'] = $skipAttributes;
				{rdelim}
				if (is_array(${$attribute->_name}Attributes['{$view->_id}'])) {ldelim}
					$keys = array_keys(${$attribute->_name}Attributes['{$view->_id}']);
					foreach ($keys as $key) {ldelim}
						if (in_array(${$attribute->_name}Attributes['{$view->_id}'][$key], ${$attribute->_name}SkipAttributes['{$view->_id}'])) {ldelim}
							unset(${$attribute->_name}Attributes['{$view->_id}'][$key]);
						{rdelim}
					{rdelim}
				{rdelim}
{else}
				$tpl->assign('attrs', FALSE);
{/if}
{if $view->_pre}
      echo '{$view->_pre}';
{/if}
{if $view->_preTemplate}
				$tpl->display('{$view->_preTemplate}');
{/if}
{* determine values to display where cardinality exists *}
{if $attribute->_cardinality}
{if $view->_idConstraint}
        $ids = {$view->_idConstraint};
        if (!is_array($ids)) {ldelim}
          $ids = array($ids);
        {rdelim}
        if (count($val)) {ldelim}
          $vkeys = array_keys($val);
          foreach ($vkeys as $vkey) {ldelim}
            if (!in_array($val[$vkey]{if $attribute->isEntity()}->getPrimaryKey(){/if}, $ids)) {ldelim}
              unset($val[$vkey]);
            {rdelim}
          {rdelim}
        {rdelim}
        foreach ($ids as $id) {ldelim}
          if ($id == 'NEW') {ldelim}
            if (!is_array($val)) {ldelim}
              $val = array();
            {rdelim}
            $val[] = {if $attribute->isEntity()}new {$attribute->_type}{$entity->_voSuffix}(){else}NULL{/if};
          {rdelim}
        {rdelim}
{/if}
				$displayCount = count($val);
{if !$view->_idConstraint}
				if ($displayCount < {$attribute->_cardinalityLower}) {ldelim}
					$displayCount = {$attribute->_cardinalityLower};
				{rdelim}
{/if}
{if $view->_multiplictyAttr}
				$test = $this->getAttribute('{$view->_multiplictyAttr}');
				if ($test >= {$attribute->_cardinalityLower} && $test <= {$attribute->_cardinalityUpper}) {ldelim}
					$displayCount = $test;
				{rdelim}
{/if}
{/if}

{* render appropriate template *}
{if $view->_template}
{if $attribute->_cardinality}
{if !$attribute->isEntity() || !$view->_renderAttributes}
{if $view->_iterate}
        $vkeys = array_keys($val);
				for ($i=0; $i<$displayCount; $i++) {ldelim}
					if (isset($val[$vkeys[$i]])) {ldelim}
						$tpl->assign{if $attribute->_useReference}ByRef{/if}('{$view->_templateVar}', $val[$vkeys[$i]]);
					{rdelim}
					else {ldelim}
						$tpl->assign('{$view->_templateVar}', FALSE);
					{rdelim}
					$tpl->assign('attributeIndex', $i + 1);
					$tpl->assign('fieldName', SRA_EntityView::getGlobalFieldNamePrefix() . $fieldName . SRA_EntityView::getGlobalFieldNamePostfix() . '_' . $i);
					$tpl->display('{$view->_template}');
				{rdelim}
				$tpl->assign('attributeIndex', FALSE);
        $tpl->assignByRef('{$smarty.const.ENTITY_VIEW_TEMPLATE_VAR_NAME}', $this);
{else}
				$tpl->assign('fieldName', {if $view->_fieldName}'{$view->_fieldName}'{else}SRA_EntityView::getGlobalFieldNamePrefix() . $fieldName . SRA_EntityView::getGlobalFieldNamePostfix(){/if});
				$tpl->display('{$view->_template}');
{/if}
{/if}
{else}
				$tpl->display('{$view->_template}');
{/if}
{/if}
        {if $view->_forwardView}$viewKey = '{$view->_forwardView}';{/if}
{if $view->_template && $view->_renderAttributes && $attribute->isEntity() && $attribute->_cardinality}
        $tpl->assign('attributeName', '{$attribute->_name}');
        $tpl->assign('attributeType', '{$attribute->_type}');
        $tpl->assign('attributeLabel', ${$attribute->_name}Labels[$viewKey]);
        $tpl->assign('fieldName', SRA_EntityView::getGlobalFieldNamePrefix() . $fieldName . SRA_EntityView::getGlobalFieldNamePostfix() . '_' . $i);
        $tpl->assign('attributeIndex', $i + 1);
        $tpl->display('{$view->_template}');
        $tpl->assign('attributeIndex', FALSE);
{/if}
        $renderAttributes = {if $attribute->isEntity() && $view->_renderAttributes}TRUE{else}FALSE{/if};
      {rdelim}
{/foreach}
{if $attribute->isEntity() && $renderAttributes}
      if ($renderAttributes) {ldelim}
			$idx = count($renderAttribute_nestedAttributes);
			$renderAttribute_nestedAttributes[$idx] = '{$attribute->_name}';
			$renderAttribute_nestedAttributeLabels[$idx] = ${$attribute->_name}Labels[$viewKey];
      $attr =& $val ? $val : $this->getAttribute($attribute);
{if $attribute->_type && !$attribute->_cardinality}
			if (!$attr && !$displayCount) {ldelim}
        require_once('{$attribute->getNestedVOName()}.{$smarty.const.SRA_SYS_PHP_EXTENSION}');
				$attr = new {$attribute->getNestedVOName()}();
				$attr->_dirty = array();
			{rdelim}
{/if}
			if ({if !$attribute->_cardinality}$attr && $attr->hasView($viewKey) && {/if}!is_array(${$attribute->_name}Attributes[$viewKey])) {ldelim}
{if $attribute->_cardinality}
				$baseNestedAttributeName = $renderAttribute_nestedAttributes[$idx];
				$akeys = array_keys($attr);
				for ($i=0; $i<$displayCount; $i++) {ldelim}
					if (!isset($akeys[$i])) {ldelim}
            require_once('{$attribute->getNestedVOName()}.{$smarty.const.SRA_SYS_PHP_EXTENSION}');
						$temp = new {$attribute->getNestedVOName()}();
						$temp->_dirty = array();
						$attr[$temp->getPrimaryKey()] =& $temp;
						$akeys[$i] = $temp->getPrimaryKey();
					{rdelim}
					if ($attr[$akeys[$i]]->hasView($viewKey)) {ldelim}
						$renderAttribute_nestedAttributes[$idx] = $baseNestedAttributeName . '_' . $i;
						$attr[$akeys[$i]]->render($viewKey, FALSE, ${$attribute->_name}SkipAttributes[$viewKey], $viewLabels, $viewValues);
					{rdelim}
				{rdelim}
{else}
				$attr->render($viewKey, FALSE, ${$attribute->_name}SkipAttributes[$viewKey], $viewLabels, $viewValues);
{/if}
			{rdelim}
			else if ({if !$attribute->_cardinality}$attr && {/if}is_array(${$attribute->_name}Attributes[$viewKey])) {ldelim}
{if $attribute->_cardinality}
				$baseNestedAttributeName = $renderAttribute_nestedAttributes[$idx];
				$akeys = array_keys($attr);
				for ($i=0; $i<$displayCount; $i++) {ldelim}
					if (!isset($akeys[$i])) {ldelim}
            require_once('{$attribute->getNestedVOName()}.{$smarty.const.SRA_SYS_PHP_EXTENSION}');
						$temp = new {$attribute->getNestedVOName()}();
						$temp->_dirty = array();
						$attr[$temp->getPrimaryKey()] =& $temp;
						$akeys[$i] = $temp->getPrimaryKey();
					{rdelim}
					$keys = array_keys(${$attribute->_name}Attributes[$viewKey]);
					$renderAttribute_nestedAttributes[$idx] = $baseNestedAttributeName . '_' . $i;
					foreach ($keys as $key) {ldelim}
						$attr[$akeys[$i]]->renderAttribute(${$attribute->_name}Attributes[$viewKey][$key], $viewKey, FALSE, ${$attribute->_name}SkipAttributes[$viewKey], $viewLabels, $viewValues);
					{rdelim}
				{rdelim}
{else}
				$keys = array_keys(${$attribute->_name}Attributes[$viewKey]);
				foreach ($keys as $key) {ldelim}
					$attr->renderAttribute(${$attribute->_name}Attributes[$viewKey][$key], $viewKey, FALSE, ${$attribute->_name}SkipAttributes[$viewKey], $viewLabels, $viewValues);
				{rdelim}
{/if}
			{rdelim}
			unset($renderAttribute_nestedAttributes[$idx]);
			unset($renderAttribute_nestedAttributeLabels[$idx]);
      $tpl->assignByRef('{$smarty.const.ENTITY_VIEW_TEMPLATE_VAR_NAME}', $this);
      {rdelim}
{/if}
{if $view->_postTemplate}
				$tpl->display('{$view->_postTemplate}');
{/if}
{if $view->_post}
      echo '{$view->_post}';
{/if}
		{rdelim}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} renderToFile
	/**
	 * renders an entity or attribute view directly to a file using output 
   * buffering. suppresses any header output related to the view. returns TRUE 
   * on success
	 * @param String $viewKey see "render" api
   * @param String $file the absolute path to the file to write the output to
   * @param String $attribute the attribute name if the $viewKey specified is 
   * for an attribute view. if not specified, $viewKey should be an entity view
   * @access public
	 * @return boolean
	 */
	function renderToFile($viewKey, $file, $attribute=NULL) {ldelim}
    {$Template->assign('aopMethodName', "renderToFile")}
    {include file="entity-aspect-before.tpl"}
    $results = FALSE;
    if (SRA_File::touch($file)) {ldelim}
      ob_start();
      $attribute ? $this->renderAttribute($attribute, $viewKey) : $this->render($viewKey, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE);
      SRA_File::write($file, ob_get_contents());
      ob_end_clean();
      $results = TRUE;
    {rdelim}
    {include file="entity-aspect-after.tpl"}
    return $results;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} renderToVar
	/**
	 * returns the render output of an entity or attribute view as a PHP variable 
   * reference
	 * @param String $viewKey see "render" api
   * @param String $attribute the attribute name if the $viewKey specified is 
   * for an attribute view. if not specified, $viewKey should be an entity view
   * @access public
	 * @return string
	 */
	function &renderToVar($viewKey, $attribute=NULL) {ldelim}
    {$Template->assign('aopMethodName', "renderToVar")}
    {include file="entity-aspect-before.tpl"}
		ob_start();
    $attribute ? $this->renderAttribute($attribute, $viewKey) : $this->render($viewKey, FALSE, FALSE, FALSE, FALSE, FALSE, TRUE);
    $var =& ob_get_contents();
    ob_end_clean();
    {include file="entity-aspect-after.tpl"}
    return $var;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// {ldelim}{ldelim}{ldelim} renderXml
	/**
	 * Renders the XML for this entity instance including any sub-entities and 
	 * referenced entities according to the DTD definition provided by the 
   * generated DTD
	 * 
   * @param array $includeAttributes the names of the attributes that should be 
   * included in the output xml. if not specified, all attributes will be 
   * included. if a string, the delimeter in the string should be a space
   * @param array $skipAttributes the names of the attributes that should NOT be
   * included in the output xml. if not specified, all attributes will be 
   * included. if a string, the delimeter in the string should be a space
   * @param SRA_ResourceBundle[] $viewResources An associative array of resource 
   * bundles that should be included in the xml rendering. These will be added 
   * utilizing nested SRA_ENTITY_MODELER_VIEW_RESOURCES_DTD_NAME elements 
   * (directly below the root xml document element). For more information, see 
   * the DTD
   * @param boolean $usePrimaryKeys if TRUE sub-entities will be rendered using 
   * their primary key value instead of the xml formatted version of those 
   * entities
   * @access public
	 * @return void
	 */
	function renderXml($includeAttributes=FALSE, $skipAttributes=FALSE, $viewResources=NULL, $usePrimaryKeys=FALSE) {ldelim}
    {$Template->assign('aopMethodName', "renderXml")}
    {include file="entity-aspect-before.tpl"}
		$tpl =& SRA_Controller::getAppTemplate();
{if $docType}
    $tpl->assign('docType', '{$docType}');
{/if}
    $tpl->assign('dtdPath', '{$dtdPath}');
    $tpl->assign('dtdUri', '{$dtdUri}');
    $xml = $this->toXmlArray($includeAttributes, $skipAttributes, $usePrimaryKeys);
    if ($viewResources && count($viewResources)) {ldelim}
      $xml['{$viewResourcesElementName}'] = array();
      $keys = array_keys($viewResources);
      $counter = 0;
      foreach($keys as $key) {ldelim}
        $xml['{$viewResourcesElementName}'][$counter] = array('attributes' => array('key' => $counter, 'id' => $key));
        $xml['{$viewResourcesElementName}'][$counter]['{$viewResourcesStringElementName}'] = array();
        $scounter = 0;
        foreach($viewResources[$key]->getData() as $id => $value) {ldelim}
          $xml['{$viewResourcesElementName}'][$counter]['{$viewResourcesStringElementName}'][$scounter] = array('attributes' => array('key' => $scounter, 'id' => $id), 'xml_value' => SRA_Util::attrToXml($value, NULL, NULL, '{$fileElementName}', $usePrimaryKeys));
          $scounter++;
        {rdelim}
        $counter++;
      {rdelim}
    {rdelim}
    $xml['attributes'] = array();
    if (SRA_Controller::isAppInitialized()) {ldelim}
      $xml['attributes']['app'] = SRA_Controller::getCurrentAppId();
      $xml['attributes']['app-path'] = SRA_Controller::getAppDir();
    {rdelim}
    $xml['attributes']['sierra-path'] = SRA_DIR;
{if $docType && ($dtdPath || $dtdUri)}
    print($tpl->fetch(SRA_LIB_DIR . '/model/entity-xml.tpl'));
{/if}
    print(SRA_XmlParser::arrayToXML(array('{if $docType}{$docType}{else}sierra-xml{/if}' => $xml)));
    {include file="entity-aspect-after.tpl"}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} serialize
	/**
	 * returns a serialization string representing this object instance. 
   * alternatively if $file is specified, TRUE will be returned if the file is 
   * written to successfully, FALSE otherwise
   * @param string $file if specified, the object will be serialized to that 
   * file. if specified, the return value will be NULL
   * @access public
	 * @return mixed
	 */
	function serialize($file=NULL) {ldelim}
    {$Template->assign('aopMethodName', "serialize")}
    {include file="entity-aspect-before.tpl"}
    $xml = $this->toXmlArray(NULL, NULL, TRUE);
    if (!is_array($xml['{$entity->getDtdName()}']['attributes'])) $xml['{$entity->getDtdName()}']['attributes'] = array();
    $xml['{$entity->getDtdName()}']['attributes']['recordExists'] = $this->recordExists;
    
    $serialized = SRA_XmlParser::arrayToXML($xml);
    if ($file) {ldelim}
      $serialized = SRA_File::write($file, $serialized) === TRUE;
    {rdelim}
    {include file="entity-aspect-after.tpl"}
    return $serialized;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} toJson
	/**
	 * returns this object instance as a json associative array where the array 
   * key is the attribute name and the value is the value for that attribute. 
   * values for attributes with cardinality will be arrays, and values for 
   * object type attributes will be nested associative array representations of 
   * those objects. the string return can be imbedded or eval'd in json code 
   * used in the frontend
	 * 
   * @param array $includeAttributes the names of the attributes that should be 
   * included in the output json. if not specified, all attributes will be 
   * included. if a string, the delimeter in the string should be a space. 
   * nested filtering is allowed using underscore as the nested attribute 
   * delimeter (i.e. 'address_zip' indicates that only the 'zip' attribute of 
   * 'address' should be included in the output)
   * @param array $skipAttributes the names of the attributes that should NOT be
   * included in the output json. if not specified, all attributes will be 
   * included. if a string, the delimeter in the string should be a space
   * nested filtering is allowed using underscore as the delimeter
   * @param SRA_ResourceBundle[] $viewResources An associative array of resource 
   * bundles that should be included in the json rendering. These will be added 
   * utilizing an additional associative object attribute named 
   * SRA_ENTITY_MODELER_VIEW_RESOURCES_DTD_NAME indexed with the same keys as 
   * the $viewResources parameter, where each value in that attribute will also 
   * be an associative array of key/value pairs providing the strings specified 
   * in that bundle
   * @param boolean $javascriptDate whether or not is $attr is a 
   * SRA_GregorianDate object, it should be converted to a javascript Date 
   * object
   * @access public
	 * @return void
	 */
	function toJson($includeAttributes=FALSE, $skipAttributes=FALSE, $viewResources=NULL, $javascriptDate=FALSE) {ldelim}
    {$Template->assign('aopMethodName', "toJson")}
    {include file="entity-aspect-before.tpl"}
    if ($includeAttributes && !is_array($includeAttributes)) {ldelim} $includeAttributes = explode(' ', $includeAttributes); {rdelim}
    if ($skipAttributes && !is_array($skipAttributes)) {ldelim} $skipAttributes = explode(' ', $skipAttributes); {rdelim}
    $includeAttributes = !is_array($includeAttributes) || !$includeAttributes || (is_array($includeAttributes) && !count($includeAttributes)) ? FALSE : $includeAttributes;
    $skipAttributes = !is_array($skipAttributes) || !$skipAttributes || (is_array($skipAttributes) && !count($skipAttributes)) ? FALSE : $skipAttributes;
    // check for recursive loop, return FALSE if loop exists
{if $primaryKey}
    static $renderingJavascript = array();
    $renderKey = $this->_{$primaryKey->_name} . ($includeAttributes ? implode('_', $includeAttributes) : '') . ($skipAttributes ? implode('_', $skipAttributes) : '');
{/if}
    if ({if $primaryKey}$renderingJavascript[$renderKey]{else}$this->_renderingJavascript{/if}) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return 'null';
    {rdelim}
{if $primaryKey}
    $renderingJavascript[$renderKey] = TRUE;
{else}
    $this->_renderingJavascript = TRUE;
{/if}
    $js = '{ldelim} "type": "{$entity->_name}"';
{foreach from=$entity->getAttributes() item=attribute}
{if !$attribute->_setOnly && !$entity->excludeAttrFromRender($attribute->_name)}
    if (SRA_Util::includeAttributeInOutput('{$attribute->_name}', $includeAttributes, $skipAttributes, $javascriptDate)) {ldelim}
      // add {$attribute->_name}
{if $attribute->_jsonView}
      $js .= ', "{$attribute->_name}": ' . SRA_Util::toJson($this->renderToVar('{$attribute->_jsonView}', '{$attribute->_name}'), NULL, NULL, $javascriptDate);
{else}
{if $attribute->isEntity()}
      $includeSubAttributes = array_merge(SRA_Util::getPrefixedArrayValues('{$attribute->_name}_', $includeAttributes), array({if $attribute->_renderInclude}{foreach from=$attribute->_renderInclude item=attr}'{$attr}', {/foreach}{/if}));
      $skipSubAttributes = array_merge(SRA_Util::getPrefixedArrayValues('{$attribute->_name}_', $skipAttributes), array({if $attribute->_renderExclude}{foreach from=$attribute->_renderExclude item=attr}'{$attr}', {/foreach}{/if}));
{/if}
{if $attribute->_cardinality && $attribute->isEntity()}
      // check if returning a specified entity
      $pks = array();
      $newIncludeSubAttributes = array();
      foreach($includeSubAttributes as $property) {ldelim}
        $pieces = explode('_', $property);
        if (is_numeric($pieces[0])) {ldelim}
          $pks[$pieces[0]] = TRUE;
          $newIncludeSubAttributes[substr($property, strlen($pieces[0]) + 1)] = TRUE;
        {rdelim}
        else {ldelim}
          $pks = NULL;
          break;
        {rdelim}
      {rdelim}
      if ($pks && count($pks)) {ldelim}
        $pks = array_keys($pks);
        $includeSubAttributes = array_keys($newIncludeSubAttributes);
        $attr = array();
        foreach($pks as $pk) {ldelim}
          $attr[$pk] ={if $attribute->_useReference}&{/if} $this->get{$attribute->getMethodName()}($pk);
        {rdelim}
      {rdelim}
      else {ldelim}
        $attr ={if $attribute->_useReference}&{/if} $this->get{$attribute->getMethodName()}();
      {rdelim}
{else}
      $attr ={if $attribute->_useReference}&{/if} $this->get{$attribute->getMethodName()}();
{/if}
{if $attribute->hasOptions() && $attribute->_renderDisplOption}
      if ($attr) {ldelim}
      // get option values
      $optionsMap =& $this->getOptionsMap('{$attribute->_name}', TRUE);
{if $attribute->_cardinality}
      $keys = array_keys($attr);
      foreach($keys as $key) {ldelim}
{/if}
      $attr{if $attribute->_cardinality}[$key]{/if} = $optionsMap[$attr{if $attribute->_cardinality}[$key]{/if}] ? $optionsMap[$attr{if $attribute->_cardinality}[$key]{/if}] : $attr{if $attribute->_cardinality}[$key]{/if};
{if $attribute->_cardinality}
      {rdelim}
{/if}
      {rdelim}
{/if}
      $js .= ', "{$attribute->_name}": ' . SRA_Util::toJson($attr{if $attribute->isEntity()}, $includeSubAttributes, $skipSubAttributes{else}, NULL, NULL{/if}, $javascriptDate);
{if $attribute->isEntity()}
      if (SRA_Util::getPrefixedArrayValues('{$attribute->_name}_', $includeAttributes)) {ldelim}
        unset($includeAttributes[array_search('{$attribute->_name}', $includeAttributes)]);
      {rdelim}
{/if}
{/if}
    {rdelim}
{/if}
{/foreach}
{foreach from=$entity->_renderAppend item=property}
    if (SRA_Util::includeAttributeInOutput('{$property}', $includeAttributes, $skipAttributes)) {ldelim}
      // add {$property}
      $attr = method_exists($this, '{$property}') ? $this->{$property}() : $this->{$property};
      $js .= ', "{$property}": ' . SRA_Util::toJson($attr, SRA_Util::getPrefixedArrayValues('{$property}_', $includeAttributes), SRA_Util::getPrefixedArrayValues('{$property}_', $skipAttributes), $javascriptDate);
      if (SRA_Util::getPrefixedArrayValues('{$property}_', $includeAttributes)) {ldelim}
        unset($includeAttributes[array_search('{$property}', $includeAttributes)]);
      {rdelim}
    {rdelim}
{/foreach}
    // check for additional values in includeAttributes
    if ($includeAttributes) {ldelim}
      foreach($includeAttributes as $method) {ldelim}
        if (method_exists($this, $method)) {ldelim}
          $attr =& $this->${ldelim}method{rdelim}();
          $js .= ', "' . $method . '": ' . SRA_Util::toJson($attr, NULL, NULL, $javascriptDate);
        {rdelim}
        else if (count($pieces = explode('_', $method)) > 1 && method_exists($this, $pieces[0])) {ldelim}
          $method = $pieces[0];
          $subAttr = NULL;
          for($i=1; $i<count($pieces); $i++) {ldelim}
            $subAttr .= $subAttr !== NULL ? '_' : '';
            $subAttr .= $pieces[$i];
          {rdelim}
          $attr =& $this->${ldelim}method{rdelim}();
          if ($subAttr) {ldelim} $subAttr = array($subAttr); {rdelim}
          $js .= ', "' . $method . '": ' . SRA_Util::toJson($attr, $subAttr, NULL, $javascriptDate);
        {rdelim}
      {rdelim}
    {rdelim}
{if $primaryKey}
    $renderingJavascript[$renderKey] = FALSE;
{else}
    $this->_renderingJavascript = FALSE;
{/if}
    
    if ($viewResources && count($viewResources)) {ldelim}
      $js .= ', "{$smarty.const.SRA_ENTITY_MODELER_VIEW_RESOURCES_DTD_NAME}": {ldelim} ';
      $keys = array_keys($viewResources);
      $started = FALSE;
      foreach($keys as $key) {ldelim}
        $js .= $started ? ', ' : '';
        $js .= '"' . $key . '": {ldelim} ';
        $started = FALSE;
        foreach($viewResources[$key]->getData() as $id => $value) {ldelim}
          $js .= $started ? ', ' : '';
          $js .= '"' . $id . '": "' . str_replace('"', '\"', $value) . '"';
          $started = TRUE;
        {rdelim}
        $js .= ' {rdelim}';
        $started = TRUE;
      {rdelim}
      $js .= ' {rdelim}';
    {rdelim}
    
    $js .= ' {rdelim}';
    {include file="entity-aspect-after.tpl"}
    return $js;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} toXmlArray
	/**
	 * Converts this {$entity->_name} instance into an associative array based on 
   * the dtd specifications for its attributes
	 * 
   * @param array $includeAttributes the names of the attributes that should be 
   * included in the output xml. if not specified, all attributes will be 
   * included. if a string, the delimeter in the string should be a space
   * @param array $skipAttributes the names of the attributes that should NOT be
   * included in the output xml. if not specified, all attributes will be 
   * included. if a string, the delimeter in the string should be a space
   * @param boolean $usePrimaryKeys if TRUE sub-entities will be rendered using 
   * their primary key value instead of the xml formatted version of those 
   * entities
   * @param boolean $camelCase whether or not to force the xml attributes and 
   * elements to camel case (otherwise, model defined format will be used)
   * @access public
	 * @return array
	 */
	function toXmlArray($includeAttributes=FALSE, $skipAttributes=FALSE, $usePrimaryKeys=FALSE, $camelCase=FALSE) {ldelim}
    {$Template->assign('aopMethodName', "toXmlArray")}
    {include file="entity-aspect-before.tpl"}
    if ($includeAttributes && !is_array($includeAttributes)) {ldelim} $includeAttributes = explode(' ', $includeAttributes); {rdelim}
    if ($skipAttributes && !is_array($skipAttributes)) {ldelim} $skipAttributes = explode(' ', $skipAttributes); {rdelim}
    $includeAttributes = !is_array($includeAttributes) || !$includeAttributes || (is_array($includeAttributes) && !count($includeAttributes)) ? FALSE : $includeAttributes;
    $skipAttributes = !is_array($skipAttributes) || !$skipAttributes || (is_array($skipAttributes) && !count($skipAttributes)) ? FALSE : $skipAttributes;
    // check for recursive loop, return FALSE if loop exists
{if $primaryKey}
    static $renderingXml = array();
    $renderKey = $this->_{$primaryKey->_name} . ($includeAttributes ? implode('_', $includeAttributes) : '') . ($skipAttributes ? implode('_', $skipAttributes) : '');
{/if}
    if ({if $primaryKey}$renderingXml[$renderKey]{else}$this->_renderingXml{/if}) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return FALSE;
    {rdelim}
{if $primaryKey}
    $renderingXml[$renderKey] = TRUE;
{else}
    $this->_renderingXml = TRUE;
{/if}
    $xml = array();
{if $entity->getDtdAttributes()}
    $xml['attributes'] = array();
{foreach from=$entity->getDtdAttributes() item=attribute}
    if (SRA_Util::includeAttributeInOutput('{$attribute->_name}', $includeAttributes, $skipAttributes)) {ldelim}
      $includeAttributes = SRA_ArrayManager::removeFromArray($includeAttributes, '{$attribute->_name}');
      // add {$attribute->_name} to xml array attributes
      $xml['attributes'][$camelCase ? '{$attribute->_name}' : '{$attribute->getDtdName()}'] = htmlspecialchars({if $attribute->_xmlView}$this->renderToVar('{$attribute->_xmlView}', '{$attribute->_name}'){else}$this->get{$attribute->getMethodName()}(){/if});
    {rdelim}
{/foreach}
{/if}
{foreach from=$entity->getDtdElements() item=attribute}
{if !$attribute->_setOnly && !$entity->excludeAttrFromRender($attribute->_name)}
    if (SRA_Util::includeAttributeInOutput('{$attribute->_name}', $includeAttributes, $skipAttributes)) {ldelim}
      $includeAttributes = SRA_ArrayManager::removeFromArray($includeAttributes, '{$attribute->_name}');
      // add {$attribute->_name} to xml array sub-elements
{if $attribute->_xmlView}
      $xml[$camelCase ? '{$attribute->_name}' : '{$attribute->getNestedElementDtdName()}'] = SRA_Util::attrToXml($this->renderToVar('{$attribute->_xmlView}', '{$attribute->_name}'), NULL, NULL, $camelCase ? 'SRA_File' : '{$fileElementName}', $usePrimaryKeys);
{else}
{if $attribute->isEntity()}
      $includeSubAttributes = array_merge(SRA_Util::getPrefixedArrayValues('{$attribute->_name}_', $includeAttributes), array({if $attribute->_renderInclude}{foreach from=$attribute->_renderInclude item=attr}'{$attr}', {/foreach}{/if}));
      $skipSubAttributes = array_merge(SRA_Util::getPrefixedArrayValues('{$attribute->_name}_', $skipAttributes), array({if $attribute->_renderExclude}{foreach from=$attribute->_renderExclude item=attr}'{$attr}', {/foreach}{/if}));
{/if}
{if $attribute->_cardinality && $attribute->isEntity()}
      // check if returning a specified entity
      $pks = array();
      $newIncludeSubAttributes = array();
      foreach($includeSubAttributes as $property) {ldelim}
        $pieces = explode('_', $property);
        if (is_numeric($pieces[0])) {ldelim}
          $pks[$pieces[0]] = TRUE;
          $newIncludeSubAttributes[substr($property, strlen($pieces[0]) + 1)] = TRUE;
        {rdelim}
        else {ldelim}
          $pks = NULL;
          break;
        {rdelim}
      {rdelim}
      if ($pks && count($pks)) {ldelim}
        $pks = array_keys($pks);
        $includeSubAttributes = array_keys($newIncludeSubAttributes);
        $attr = array();
        foreach($pks as $pk) {ldelim}
          $attr[$pk] ={if $attribute->_useReference}&{/if} $this->get{$attribute->getMethodName()}($pk);
        {rdelim}
      {rdelim}
      else {ldelim}
        $attr ={if $attribute->_useReference}&{/if} $this->get{$attribute->getMethodName()}();
      {rdelim}
{else}
      $attr ={if $attribute->_useReference}&{/if} $this->get{$attribute->getMethodName()}();
{if $attribute->hasOptions() && $attribute->_renderDisplOption}
      if ($attr) {ldelim}
      // get option values
      $optionsMap =& $this->getOptionsMap('{$attribute->_name}', TRUE);
{if $attribute->_cardinality}
      $keys = array_keys($attr);
      foreach($keys as $key) {ldelim}
{/if}
      $attr{if $attribute->_cardinality}[$key]{/if} = $optionsMap[$attr{if $attribute->_cardinality}[$key]{/if}] ? $optionsMap[$attr{if $attribute->_cardinality}[$key]{/if}] : $attr{if $attribute->_cardinality}[$key]{/if};
{if $attribute->_cardinality}
      {rdelim}
{/if}
      {rdelim}
{/if}
{/if}

{if !$attribute->_cardinalityLower}
      if ({if $attribute->_cardinality}is_array($attr) && count({else}isset({/if}$attr)) {ldelim}
{/if}
      $xml[$camelCase ? '{$attribute->_name}' : '{$attribute->getNestedElementDtdName()}'] = {if $attribute->_cardinality}$attr{else}SRA_Util::attrToXml($attr, {if $attribute->isEntity()}$includeSubAttributes, $skipSubAttributes{else}NULL, NULL{/if}, $camelCase ? 'SRA_File' : '{$fileElementName}', $usePrimaryKeys){/if};
{if $attribute->isEntity() && $entity->attrIsPersistent($attribute->_name)}
      if ($usePrimaryKeys) {ldelim}
        $tmp = $xml[$camelCase ? '{$attribute->_name}' : '{$attribute->getNestedElementDtdName()}'];
        $xml[$camelCase ? '{$attribute->_name}' : '{$attribute->getNestedElementDtdName()}'] = array();
        foreach({if $attribute->_cardinality}$tmp{else}array($tmp){/if} as $pk) {ldelim}
          $xml[$camelCase ? '{$attribute->_name}' : '{$attribute->getNestedElementDtdName()}'][$pk] = array('attributes' => array('key' => $pk));
        {rdelim}
      {rdelim}
      if (SRA_Util::getPrefixedArrayValues('{$attribute->_name}_', $includeAttributes)) {ldelim}
        unset($includeAttributes[array_search('{$attribute->_name}', $includeAttributes)]);
      {rdelim}
{/if}
{if $attribute->_cardinality}
      $tmp = $xml[$camelCase ? '{$attribute->_name}' : '{$attribute->getNestedElementDtdName()}'];
      $xml[$camelCase ? '{$attribute->_name}' : '{$attribute->getNestedElementDtdName()}'] = array();
      foreach(array_keys($tmp) as $key) {ldelim}
{if $attribute->isEntity()}
        if ($usePrimaryKeys && {$attribute->_type}{$entity->_voSuffix}::entityHasPersistence()) {ldelim}
          $tmp[$key]['attributes'] = array('key' => $key);
          $xml[$camelCase ? '{$attribute->_name}' : '{$attribute->getNestedElementDtdName()}'][$key] = $tmp[$key];
        {rdelim}
        else {ldelim}
          $xml[$camelCase ? '{$attribute->_name}' : '{$attribute->getNestedElementDtdName()}'][] = $tmp[$key]->toXmlArray(SRA_Util::getPrefixedArrayValues('{$attribute->_name}_', $includeAttributes), SRA_Util::getPrefixedArrayValues('{$attribute->_name}_', $skipAttributes), $usePrimaryKeys, $camelCase);
        {rdelim}
{else}
        $tmp[$key] = array('attributes' => array('key' => $key, '_akey' => $key), 'xml_value' => SRA_Util::attrToXml($tmp[$key], NULL, NULL, $camelCase ? 'SRA_File' : '{$fileElementName}', $usePrimaryKeys));
        $xml[$camelCase ? '{$attribute->_name}' : '{$attribute->getNestedElementDtdName()}'][$key] = $tmp[$key];
{/if}
      {rdelim}
{/if}
{if !$attribute->_cardinalityLower}
      {rdelim}
{/if}
{/if}
    {rdelim}
{/if}
{/foreach}

{foreach from=$entity->_renderAppend item=property}
    if (SRA_Util::includeAttributeInOutput('{$property}', $includeAttributes, $skipAttributes)) {ldelim}
      // add {$property}
      $includeAttributes = SRA_ArrayManager::removeFromArray($includeAttributes, '{$property}');
      $attr = method_exists($this, '{$property}') ? $this->{$property}() : $this->{$property};
      $xml[$camelCase ? '{$property}' : '{$entity->getDtdSubElementName($property)}'] = SRA_Util::attrToXml($attr, SRA_Util::getPrefixedArrayValues('{$property}_', $includeAttributes), SRA_Util::getPrefixedArrayValues('{$property}_', $skipAttributes), $camelCase ? 'SRA_File' : '{$fileElementName}', $usePrimaryKeys);
      if (SRA_Util::getPrefixedArrayValues('{$property}_', $includeAttributes)) {ldelim}
        unset($includeAttributes[array_search('{$property}', $includeAttributes)]);
      {rdelim}
    {rdelim}
{/foreach}

    // check for additional values in includeAttributes
    if ($includeAttributes) {ldelim}
      foreach($includeAttributes as $method) {ldelim}
        if (method_exists($this, $method)) {ldelim}
          $attr =& $this->${ldelim}method{rdelim}();
          $xml[$camelCase ? $method : {if $entity->_dtdCamelCase}$method{else}SRA_Util::camelCaseToDashes($method){/if}] = SRA_Util::attrToXml($attr, SRA_Util::getPrefixedArrayValues('{$property}_', $includeAttributes), SRA_Util::getPrefixedArrayValues('{$property}_', $skipAttributes), $camelCase ? 'SRA_File' : '{$fileElementName}', $usePrimaryKeys);
        {rdelim}
        else if (count($pieces = explode('_', $method)) > 1 && method_exists($this, $pieces[0])) {ldelim}
          $method = $pieces[0];
          $subAttr = NULL;
          for($i=1; $i<count($pieces); $i++) {ldelim}
            $subAttr .= $subAttr !== NULL ? '_' : '';
            $subAttr .= $pieces[$i];
          {rdelim}
          $attr =& $this->${ldelim}method{rdelim}();
          if ($subAttr) {ldelim} $subAttr = array($subAttr); {rdelim}
          $xml[$camelCase ? $method : {if $entity->_dtdCamelCase}$method{else}SRA_Util::camelCaseToDashes($method){/if}] = SRA_Util::attrToXml($attr, $subAttr);
        {rdelim}
      {rdelim}
    {rdelim}
    
{if $primaryKey}
    $renderingXml[$renderKey] = FALSE;
{else}
    $this->_renderingXml = FALSE;
{/if}
    {include file="entity-aspect-after.tpl"}
    return array($camelCase ? '{$entity->_name}' : '{$entity->getDtdName()}' => $xml);
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} getDtdName
	/**
	 * returns the dtd name for this entity
   * @access public
	 * @return string
	 */
	function getDtdName() {ldelim}
    {$Template->assign('aopMethodName', "getDtdName")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    return '{$entity->getDtdName()}';
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} getWsAttributes
	/**
	 * returns an array of all of the attributes that will be included in a web 
   * service output
   * @access public
	 * @return array
	 */
	function getWsAttributes() {ldelim}
    {$Template->assign('aopMethodName', "getWsAttributes")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    {assign var=started value=0}
    return array({foreach from=$entity->getDtdAttributes(1) item=attribute}{if $started}, {/if}'{$attribute->_name}'{assign var=started value=1}{/foreach}{foreach from=$entity->getDtdElements(1) item=attribute}{if $started}, {/if}'{$attribute->_name}'{assign var=started value=1}{/foreach}{foreach from=$entity->_renderAppend item=property}{if $started}, {/if}'{$property}'{assign var=started value=1}{/foreach});
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} isAttributeReadOnly
	/**
	 * returns TRUE if the attribute $attr is read only
   * @param $attr the name of the attribute
   * @access public
	 * @return boolean
	 */
	function isAttributeReadOnly($attr) {ldelim}
    {$Template->assign('aopMethodName', "isAttributeReadOnly")}
    {include file="entity-aspect-before.tpl"}
    switch ($attr) {ldelim}
{foreach from=$entity->getAttributes() item=attribute}
      case '{$attribute->_name}':
{if $attribute->getAggregateAttributes()}
{foreach from=$attribute->getAggregateAttributes() item=attr}
      case '{$attr->_name}':
{/foreach}
{/if}
        $ret = {if $attribute->_readOnly}TRUE{else}FALSE{/if};
        break;
{/foreach}
      default:
        $ret = TRUE;
    {rdelim}
    {include file="entity-aspect-after.tpl"}
    return $ret;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} isAttributeSetOnly
	/**
	 * returns TRUE if the attribute $attr is set only
   * @param $attr the name of the attribute
   * @access public
	 * @return boolean
	 */
	function isAttributeSetOnly($attr) {ldelim}
    {$Template->assign('aopMethodName', "isAttributeSetOnly")}
    {include file="entity-aspect-before.tpl"}
    switch ($attr) {ldelim}
{foreach from=$entity->getAttributes() item=attribute}
      case '{$attribute->_name}':
        $ret = {if $attribute->_setOnly}TRUE{else}FALSE{/if};
        break;
{/foreach}
      default:
        $ret = TRUE;
    {rdelim}
    {include file="entity-aspect-after.tpl"}
    return $ret;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} getWsdl
	/**
	 * returns the wsdl associated with this entity
   * @param array $includeAttributes the names of the attributes that should be 
   * included in the output xml. if not specified, all attributes will be 
   * included. if a string, the delimeter in the string should be a space
   * @param array $skipAttributes the names of the attributes that should NOT be
   * included in the output xml. if not specified, all attributes will be 
   * included. if a string, the delimeter in the string should be a space
   * @param string $spacesPre space characters to prefix to each wsdl line
   * @access public
	 * @return string
	 */
	function getWsdl($includeAttributes=FALSE, $skipAttributes=FALSE, $spacesPre = '') {ldelim}
{if $entity->_skipWsdl}
    return '';
{else}
    {$Template->assign('aopMethodName', "getWsdl")}
    {include file="entity-aspect-before.tpl"}
    if ($includeAttributes && !is_array($includeAttributes)) {ldelim} $includeAttributes = explode(' ', $includeAttributes); {rdelim}
    if ($skipAttributes && !is_array($skipAttributes)) {ldelim} $skipAttributes = explode(' ', $skipAttributes); {rdelim}
    $includeAttributes = !is_array($includeAttributes) || !$includeAttributes || (is_array($includeAttributes) && !count($includeAttributes)) ? FALSE : $includeAttributes;
    $skipAttributes = !is_array($skipAttributes) || !$skipAttributes || (is_array($skipAttributes) && !count($skipAttributes)) ? FALSE : $skipAttributes;
    
    $wsdl .= $spacesPre . '<complexType name="{$entity->_name}">' . "\n";
{if $entity->getDtdAttributes()}
{foreach from=$entity->getDtdAttributes() item=attribute}
{if !$attribute->_skipWsdl && !$attribute->_setOnly && !$entity->excludeAttrFromRender($attribute->_name)}
    if (SRA_Util::includeAttributeInOutput('{$attribute->_name}', $includeAttributes, $skipAttributes)) {ldelim}
      // add {$attribute->_name} to wsdl attributes
      $wsdl .= $spacesPre . '  <attribute name="{$attribute->_name}" type="{$attribute->getWsdlType()}" use="{if $attribute->isRequired() || $attribute->_name eq $primaryKey->_name}required{else}optional{/if}" />' . "\n";
    {rdelim}
{/if}
{/foreach}
{/if}
    $wsdl .= $spacesPre . "  <sequence>\n";
{foreach from=$entity->getDtdElements() item=attribute}
{if !$attribute->_skipWsdl && !$attribute->_setOnly && !$entity->excludeAttrFromRender($attribute->_name)}
    if (SRA_Util::includeAttributeInOutput('{$attribute->_name}', $includeAttributes, $skipAttributes)) {ldelim}
      // add {$attribute->_name} to wsdl sub-elements
      $wsdl .= $spacesPre . '    <element minOccurs="{if $attribute->isRequired() || $attribute->_name eq $primaryKey->_name}1{else}0{/if}" maxOccurs="{if $attribute->_cardinality}{if $attribute->_cardinalityUpper eq $smarty.const.SRA_MAX_INT_VAL}unbounded{else}{$attribute->_cardinalityUpper}{/if}{else}1{/if}" name="{$attribute->_name}" type="{$attribute->getWsdlType()}" />' . "\n";
    {rdelim}
{/if}
{/foreach}

{foreach from=$entity->_renderAppend item=property}
    if (SRA_Util::includeAttributeInOutput('{$property}', $includeAttributes, $skipAttributes)) {ldelim}
      // add {$property}
      $wsdl .= $spacesPre . '    <element minOccurs="0" maxOccurs="1" name="{$property}" type="xsd:string" />' . "\n";
    {rdelim}
{/foreach}
    
    $wsdl .= $spacesPre . "  </sequence>\n";
    $wsdl .= $spacesPre . "</complexType>";
    
    {include file="entity-aspect-after.tpl"}
    return $wsdl;
{/if}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} skipWsdl
	/**
	 * returns TRUE if this entity should be skipped from the wsdl generated by 
   * the model web services
   * @access public static
	 * @return boolean
	 */
	function skipWsdl() {ldelim}
    {$Template->assign('aopMethodName', "skipWsdl")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
    return {if $entity->_skipWsdl}TRUE{else}FALSE{/if};
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// {ldelim}{ldelim}{ldelim} _writeRenderOutput
	/**
	 * Renders the DTD for this entity and any sub-entities. referenced entities 
	 * will need to be added to this DTD to construct a full DTD for the 
	 * entity-model. the DTD definition will only be generated where 
	 * skip-persistence is not TRUE
	 * 
	 * @param String $file a file to render the DTD to. if not specified, the 
	 * xml will be output to the standard output using print
	 * @param String $mode the fopen mode to use if the $file parameter is 
	 * specified. the default mode is to append to that file
	 * @param boolean $finish whether or not the output rendering is finished 
	 * (file pointer will be closed if necessary)
   * @access public static
	 * @return void on success or SRA_Error object otherwises
	 */
	function _writeRenderOutput($msg, $file, $mode, $finish=FALSE) {ldelim}
    {$Template->assign('aopMethodName', "_writeRenderOutput")}
    {include file="entity-aspect-before.tpl"}
		static $openFps = array();
		if ($file && !isset($openFps[$file])) {ldelim}
			$openFps[$file] = fopen($file, $mode);
		{rdelim}
		if ($file) {ldelim}
			fwrite($openFps[$file], $msg . "\n");
		{rdelim}
		else {ldelim}
			print($msg . "\n");
		{rdelim}
		if ($file && $finish) {ldelim}
			fclose($openFps[$file]);
			unset($openFps[$file]);
		{rdelim}
    {include file="entity-aspect-after.tpl"}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// {ldelim}{ldelim}{ldelim} hasView
	/**
	 * Returns TRUE if this entity has a particular view defines
	 * 
	 * @param String $viewKey the identifier of the view to check for. if not 
	 * specified, returns TRUE only if a default view has been defined
	 * @param String $attribute if specified, checks if the view exists for that 
	 * attribute
	 * @return TRUE if the view exists, FALSE otherwise
	 * @access public
	 */
	function hasView($viewKey = FALSE, $attribute = FALSE) {ldelim}
    {$Template->assign('aopMethodName', "hasView")}
    {include file="entity-aspect-before.tpl"}
		if ($attribute) {ldelim}
{foreach from=$entity->getAttributes() item=attribute}
			if ('{$attribute->_name}' == $attribute) {ldelim}
{foreach from=$attribute->_views item=view}
				if ($viewKey == '{$view->_id}'{if $view->_default} || !$viewKey{/if}) {ldelim}
          {include file="entity-aspect-after.tpl"}
					return TRUE;
				{rdelim}
{/foreach}
			{rdelim}
{/foreach}
		{rdelim}
		else {ldelim}
{foreach from=$entity->_views item=view}
			if ($viewKey == '{$view->_id}'{if $view->_default} || !$viewKey{/if}) {ldelim}
        {include file="entity-aspect-after.tpl"}
				return TRUE;
			{rdelim}
{/foreach}
		{rdelim}
		// view not found
    {include file="entity-aspect-after.tpl"}
		return FALSE;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// {ldelim}{ldelim}{ldelim} parseString
	/**
	 * Parses a string containing imbedded entity value identifiers in the format: 
	 *   {ldelim}$attr[_subAttr]{rdelim} OR
	 *   {ldelim}$getLabel([attr]){rdelim} OR 
	 *   {ldelim}$getString([key]){rdelim} : [key] will be translated using the 
	 *                                       current resource bundle for the user
	 *                                       entity, app and system bundles
	 * where each occurrence of these identifiers will be replaced with the value 
	 * returned by this entity's getAttribute(attr) method. if this method returns 
	 * an object for that attribute, it will be serialized unless it contains a 
	 * "toString" method, in which case the value of that method call will be 
	 * substituted
	 * 
	 * @param string $str the string to parse
	 * @param boolean $checkPrefix whether or not restrict parsing to only if $str
	 * is prefixed with "parse:"
	 * @return the same string with entity attributes parsed out
	 * @access public
	 */
	function parseString($str, $checkPrefix=FALSE) {ldelim}
    {$Template->assign('aopMethodName', "parseString")}
    {include file="entity-aspect-before.tpl"}
		if ($checkPrefix && !SRA_Util::beginsWith($str, 'parse:')) {ldelim}
			return $str;
		{rdelim}
		else if ($checkPrefix) {ldelim}
			$str = substr($str, strlen('parse:'));
		{rdelim}
		$rb =& {$className}::getEntityResources();
		$pos = 0;
		while (($pos = strpos($str, '{ldelim}$', $pos)) !== FALSE) {ldelim}
			if (($end = strpos($str, '{rdelim}', $pos + 2)) !== FALSE) {ldelim}
				$key = substr($str, $pos + 2, $end - $pos - 2);
				$baseKey = $key;
				if (strstr($key, 'getLabel')) {ldelim}
					$key = str_replace('getLabel(', '', $key);
					$key = trim(str_replace(')', '', $key));
					$key = strlen($key) > 0 ? $key : FALSE;
					$val = $this->getEntityLabel($key);
				{rdelim}
				else if (strstr($key, 'getString')) {ldelim}
					$key = str_replace('getString(', '', $key);
					$key = trim(str_replace(')', '', $key));
					if (substr($key, 0, 1) == "'" || substr($key, 0, 1) == '"') {ldelim}
						$key = substr($key, 1);
					{rdelim}
					if (substr($key, 0, -1) == "'" || substr($key, 0, -1) == '"') {ldelim}
						$key = substr($key, 0, strlen($key) - 1);
					{rdelim}
					$val = $rb->getString($key);
				{rdelim}
				else if ($key == 'renderEntityName') {ldelim}
					$val = '{$entity->_name}';
				{rdelim}
				else if ($key == 'renderAttributeName') {ldelim}
					$val = $this->_renderAttributeName;
				{rdelim}
				else {ldelim}
					$val =& $this->getAttribute($key);
				{rdelim}
				if (is_object($val)) {ldelim}
					if (method_exists($val, 'toString')) {ldelim}
						$val = $val->toString();
					{rdelim}
					else {ldelim}
						$val = serialize($val);
					{rdelim}
				{rdelim}
				$str = str_replace('{ldelim}$' . $baseKey . '{rdelim}', $val, $str);
			{rdelim}
			$pos++;
		{rdelim}
    {include file="entity-aspect-after.tpl"}
		return $str;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}


	//*** SETTERS ***//
	// {ldelim}{ldelim}{ldelim} setAttributes
	/**
   * sets multiple attributes simultaneously
	 * @param array $attrs an associative array of attributes to set. Any values 
   * in this array where the array index key is equal to an attribute name will 
   * be used to set that corresponding attribute value. Attribute names in this 
   * parameter should not be prefixed with an underscore _. the following naming 
   * conventions apply to values in this array:
   *    Attribute Is:      Valid Keys           Valid Values
   *    scalar 1..1        name                 scalar value  or null
   *                       name_remove          set value to null
   *    scalar n..*        name                 scalar value or array. scalar 
   *                                            will be added to existing values
   *                                            while array will replace them. null
   *                                            will result in this attribute being 
   *                                            set to null
   *                       name_remove          scalar value or array. this value or values 
   *                                            will be removed from the existing 
   *                                            array value (if present)
   *    entity 1..1        name                 a valid reference to that entity or null
   *                       name_[sub name]      one ore more entity attributes 
   *                                            a new entity will be instantiated 
   *                                            where the keys will be [sub name]
   *                                            values and the values will be 
   *                                            the asssociated values
   *                       name_[sub name]_remove used to specify that the attribute 
   *                                            specified by [sub name] should be removed
   *    entity n..*        name                 an array of references to that entity
   *                                            or a single reference. the former 
   *                                            will replace the current values 
   *                                            for the attribute, while the latter 
   *                                            will simply add a new entity to 
   *                                            the existing values. null will set this
   *                                            attribute to null
   *                       name_[idx][_[sub name]] used to specify multiple non-instantiated 
   *                                            entities. these will be instantiated 
   *                                            where the keys will be [sub name]
   *                                            values and the values will be 
   *                                            the asssociated values. the resulting 
   *                                            entity array will be ADDED to the 
   *                                            existing entities for this class 
   *                                            UNLESS one of the [sub name] values 
   *                                            is the name and value of a primary 
   *                                            key for that entity type. if "_[sub name]" 
   *                                            is not specified, it will be assumed
   *                                            to be the primary key
   *                       name_[idx]_[sub name]_remove used to specify that the attribute 
   *                                            specified by [sub name] should be removed
   *                       name_[pk]_remove     set to 1 to remove the corresponding 
   *                                            entity identified by the primary key 
   *                                            pk
   *                                            
   *    entity attributes will always be checked first against existing entities 
   *    set for that attribute. if they are already set, then the new attributes 
   *    will simply be updated (using setAttribute). in the end, if that entity 
   *    is dirty, the dirty flag will be set in this entity for that attribute
   *
   * If the primary key is included in the initialization values, that object 
   * will be instantiated from the database and its' attributes overriden if 
   * they are included in $initVals
   * 
	 * @param boolean $appendDirty whether or not the _dirty attribute should be 
	 * appended to reflect values set from the $attrs parameter will be 
	 * considered _dirty changes. If TRUE, default values will also be set for 
	 * this entity
	 * @return void
	 * @access public
	 */
	function setAttributes(&$attrs, $appendDirty = TRUE) {ldelim}
    {$Template->assign('aopMethodName', "setAttributes")}
    {include file="entity-aspect-before.tpl"}
    $nl = NULL;
		if (is_array($attrs)) {ldelim}
			$keys = array_keys($attrs);
			foreach ($keys as $key) {ldelim}
{assign var=started value="0"}
{foreach from=$entity->getAttributes() item=attribute}
{* scalar attributes *}
{if !$attribute->isEntity()}
        {if $started}else {/if}if ('{$attribute->_name}' == $key || strpos($key, '{$attribute->_name}_{if !$attribute->_cardinality}remove{/if}') === 0) {ldelim}
{* no cardinality *}
{if !$attribute->_cardinality}
          if (strpos($key, '{$attribute->_name}_remove') === 0) {ldelim}
            if ($attrs[$key] == '1') {ldelim}
              $this->set{$attribute->getMethodName()}($nl, $appendDirty);
            {rdelim}
          {rdelim}
          else {ldelim}
            $this->set{$attribute->getMethodName()}($attrs[$key], $appendDirty);
          {rdelim}
{* with cardinality *}
{else}
          if (SRA_Util::endsWith($key, '_remove')) {ldelim}
            $this->remove{$attribute->getMethodName()}($attrs[$key], $appendDirty);
          {rdelim}
          else {ldelim}
            if (is_array($attrs[$key])) {ldelim}
              $this->set{$attribute->getMethodName()}($attrs[$key], $appendDirty);
            {rdelim}
            else {ldelim}
              $this->add{$attribute->getMethodName()}($attrs[$key], $appendDirty);
            {rdelim}
          {rdelim}
{/if}


{* entity attributes *}
{else}
        {if $started}else {/if}if ('{$attribute->_name}' == $key || $key == '{$attribute->_name}_remove') {ldelim}
{* no cardinality *}
{if !$attribute->_cardinality}
          if ($key == '{$attribute->_name}_remove') {ldelim}
            if ($attrs[$key] == '1') {ldelim}
              $this->set{$attribute->getMethodName()}($nl, $appendDirty);
            {rdelim}
          {rdelim}
          else {ldelim}
            $this->set{$attribute->getMethodName()}($attrs[$key], $appendDirty);
          {rdelim}
{* with cardinality *}
{else}
          if ($key == '{$attribute->_name}_remove') {ldelim}
            $this->remove{$attribute->getMethodName()}($attrs[$key], $appendDirty);
          {rdelim}
          else {ldelim}
            if (is_array($attrs[$key])) {ldelim}
              $this->set{$attribute->getMethodName()}($attrs[$key], $appendDirty);
            {rdelim}
            else {ldelim}
              $this->add{$attribute->getMethodName()}($attrs[$key], $appendDirty);
            {rdelim}
          {rdelim}
{/if}
        {rdelim}
        else if (strpos($key, '{$attribute->_name}_') === 0) {ldelim}
{* no cardinality *}
{if !$attribute->_cardinality}
          $sub = substr($key, strlen('{$attribute->_name}_'));
          if (!is_array(${$attribute->_name}InitVals)) {ldelim}
            ${$attribute->_name}InitVals = array();
          {rdelim}
          ${$attribute->_name}InitVals[$sub] = $attrs[$key];
{* with cardinality *}
{else}
          $pieces = explode('_', $key);
          // primary key
          if (count($pieces) == 2) {ldelim}
            $pieces[2] = '{$attribute->getEntityPkName()}';
          {rdelim}
          if (count($pieces) > 2) {ldelim}
            $idx = $pieces[1];
            $sub = $pieces[2];
            for($i=3; $i<count($pieces); $i++) {ldelim}
              $sub .= '_' . $pieces[$i];
            {rdelim}
            if ($pieces[2] == 'remove') {ldelim}
              if ($attrs[$key] == '1') {ldelim}
                $this->remove{$attribute->getMethodName()}($pieces[1]);
              {rdelim}
            {rdelim}
            else {ldelim}
              if (!is_array(${$attribute->_name}InitVals)) {ldelim}
                ${$attribute->_name}InitVals = array();
              {rdelim}
              if (!is_array(${$attribute->_name}InitVals[$pieces[1]])) {ldelim}
                ${$attribute->_name}InitVals[$pieces[1]] = array();
              {rdelim}
              ${$attribute->_name}InitVals[$pieces[1]][$sub] = $attrs[$key];
            {rdelim}
          {rdelim}
          else {ldelim}
            $msg = "{$className}::setAttributes: Error - Invalid attribute key: $key";
            SRA_Error::logError($msg, __FILE__, __LINE__);
          {rdelim}
{/if}
{/if}
        {rdelim}
{if $attribute->getAggregateAttributes()}
        // mapped attributes for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
        {if $started}else {/if}if ('{$attr->_name}' == $key || strpos($key, '{$attr->_name}_remove') === 0) {ldelim}
{* no cardinality *}
{if !$attr->_cardinality}
          if (strpos($key, '{$attr->_name}_remove') === 0) {ldelim}
            if ($attrs[$key] == '1') {ldelim}
              $this->set{$attr->getMethodName()}($nl, $appendDirty);
            {rdelim}
          {rdelim}
          else {ldelim}
            $this->set{$attr->getMethodName()}($attrs[$key], $appendDirty);
          {rdelim}
{* with cardinality *}
{else}
          if (strpos($key, '{$attr->_name}_remove') === 0) {ldelim}
            $this->remove{$attr->getMethodName()}($attrs[$key], $appendDirty);
          {rdelim}
          else {ldelim}
            if (is_array($attrs[$key])) {ldelim}
              $this->set{$attr->getMethodName()}($attrs[$key], $appendDirty);
            {rdelim}
            else {ldelim}
              $this->add{$attr->getMethodName()}($attrs[$key], $appendDirty);
            {rdelim}
          {rdelim}
{/if}
        {rdelim}
{/foreach}
{/if}
{assign var=started value="1"}
{/foreach}
      {rdelim}
    {rdelim}
        
{* initialize entity attributes that have been provided in the init values using _ *}
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->isEntity()}
    if (isset(${$attribute->_name}InitVals)) {ldelim}
{* no cardinality *}
{if !$attribute->_cardinality}
      if ($this->get{$attribute->getMethodName()}()) {ldelim}
        $this->_{$attribute->_name}->setAttributes(${$attribute->_name}InitVals);
      {rdelim}
      else {ldelim}
        require_once('{$attribute->_type}{$entity->_voSuffix}.{$smarty.const.SRA_SYS_PHP_EXTENSION}');
        $tmp = new {$attribute->_type}{$entity->_voSuffix}(${$attribute->_name}InitVals);
        $this->set{$attribute->getMethodName()}($tmp);
      {rdelim}
{* with cardinality *}
{else}
      ${$attribute->_name} = array();
      $counter = 0;
      $keys = array_keys(${$attribute->_name}InitVals);
      foreach ($keys as $key) {ldelim}
        // only add if it hasn't already been removed
        require_once('{$attribute->_type}{$entity->_voSuffix}.{$smarty.const.SRA_SYS_PHP_EXTENSION}');
        ${$attribute->_name}[$counter] = new {$attribute->_type}{$entity->_voSuffix}(${$attribute->_name}InitVals[$key]);
        if (!${$attribute->_name}[$counter]->getPrimaryKey() || !isset($this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY][${$attribute->_name}[$counter]->getPrimaryKey()])) {ldelim}
          $counter++;
        {rdelim}
        else {ldelim}
          unset(${$attribute->_name}[$counter]);
        {rdelim}
      {rdelim}
      if (count(${$attribute->_name})) {ldelim} $this->add{$attribute->getMethodName()}(${$attribute->_name}); {rdelim}
{/if}
    {rdelim}
{/if}
{/foreach}
    
    {include file="entity-aspect-after.tpl"}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} setAttribute
	/**
	 * Sets the value of an attribute based on its name
	 * 
	 * @param string $name the name of the attribute to set
	 * @param mixed $val the value to set
	 * @param boolean $appendDirty whether or not the _dirty attribute should be 
	 * appended to reflect changes made
	 * @return the return value from the setter
	 * @access public
	 */
	function setAttribute($name, $val, $appendDirty = TRUE) {ldelim}
    {$Template->assign('aopMethodName', "setAttribute")}
    {include file="entity-aspect-before.tpl"}
		if (method_exists($this, $name)) {ldelim}
      {include file="entity-aspect-after.tpl"}
			return $this->${ldelim}name{rdelim}($val);
		{rdelim}
{foreach from=$entity->getAttributes() item=attribute}
		if ('{$attribute->_name}' == $name) {ldelim}
      {include file="entity-aspect-after.tpl"}
			return $this->set{$attribute->getMethodName()}($val, $appendDirty);
		{rdelim}
{if $attribute->isEntity()}
		if (strpos($name, '{$attribute->_name}_') === 0) {ldelim}
{if $attribute->_cardinality}
			$pk = FALSE;
			if (count($pieces = explode('_', $name)) == 3) {ldelim}
				$pk = $pieces[1];
			{rdelim}
{/if}
			if ({$attribute->_type}{$entity->_voSuffix}::isValid($attr ={if $attribute->_useReference}& {/if}$this->get{$attribute->getMethodName()}({if $attribute->_cardinality}$pk{/if}))) {ldelim}
				$attrName = str_replace('{$attribute->_name}_', '', $name);
{if $attribute->_cardinality}
				if ($pk) {ldelim}
					$attrName = str_replace($pk . '_', '', $attrName);
					{rdelim}
{/if}
        {include file="entity-aspect-after.tpl"}
				return $attr->setAttribute($attrName, $val, $appendDirty);
			{rdelim}
		{rdelim}
{if $attribute->getAggregateAttributes()}
    // mapped attributes for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{if !$attr->_readOnly}
    if ('{$attr->_name}' == $name) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return $this->set{$attr->getMethodName()}($val, $appendDirty);
    {rdelim}
{/if}
{/foreach}
{/if}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
		return FALSE;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
{foreach from=$entity->getAttributes() item=attribute}
{assign var="methodName" value="set"|cat:$attribute->getMethodName()}
	// {ldelim}{ldelim}{ldelim} {$methodName}
	/**
	 * Setter for <code>_{$attribute->_name}</code>
	 * {if $attribute->_apiResource}{$resources->getString($attribute->_apiResource)}{/if} 
	 * 
	 * @param {if $attribute->_isFile}SRA_FileAttribute or PHP $_FILE array or absolute/relative file path{else}{$attribute->_type}{/if} ${$attribute->_name} the value to set
{if $attribute->_cardinality}
   * any existing values not in this array of values will be removed
{/if}
	 * @param boolean $appendDirty whether or not the _dirty attribute should be 
	 * appended to reflect changes made
	 * @return FALSE on success, a localized error message otherwise
	 * @access public
	 */
	function {$methodName}( {if $attribute->_useReference}& {/if}${$attribute->_name}, $appendDirty = TRUE ) {ldelim}
    {$Template->assign('aopMethodName', $methodName)}
    {include file="entity-aspect-before.tpl"}
    $ret = FALSE;
{if $attribute->_matchUserId}
    if (!$this->_matchUserId('{$attribute->_matchUserId}', 'get{$attribute->getMethodName()}')) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return FALSE;
    {rdelim}
{/if}
{if $attribute->_readOnly}
    // this attribute is read-only and cannot be modified
    if ($appendDirty) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return FALSE;
    {rdelim}
{/if}

{if $attribute->_cardinality}
    if (!is_array(${$attribute->_name})) {ldelim}
      $isNULL = ${$attribute->_name} === NULL;
      ${$attribute->_name} = array(${$attribute->_name});
    {rdelim}
    // determine which attributes to remove
    if ($appendDirty && ($current ={if $attribute->_useReference}&{/if} $this->get{$attribute->getMethodName()}())) {ldelim}
      $keys = array_keys($current);
      foreach ($keys as $key) {ldelim}
        $found = FALSE;
        $nkeys = array_keys(${$attribute->_name});
        foreach($nkeys as $nkey) {ldelim}
{if $attribute->isEntity() && !$attribute->isEntitySkipPersistence()}
          if (is_scalar(${$attribute->_name}[$nkey])) {ldelim}
            $dao =& SRA_DaoFactory::getDao('{$attribute->_type}');
            ${$attribute->_name}[$nkey] =& $dao->findByPk(${$attribute->_name}[$nkey]);
          {rdelim}
          if (isset($this->_linkedAttributes['{$attribute->_name}'][$current[$key]->getPrimaryKey()])) {ldelim}
            $found = TRUE;
            break;
          {rdelim}
          if ({$attribute->_type}{$entity->_voSuffix}::isValid(${$attribute->_name}[$nkey])) {ldelim}
{/if}
          if (SRA_Util::equal(${$attribute->_name}[$nkey], $current[$key])) {ldelim}
            $found = TRUE;
            break;
          {rdelim}
{if $attribute->isEntity() && !$attribute->isEntitySkipPersistence()}
          {rdelim}
{/if}
        {rdelim}
        if (!$found) {ldelim}
          $this->remove{$attribute->getMethodName()}($current[$key]);
        {rdelim}
      {rdelim}
      if ($isNULL) {ldelim} $this->_{$attribute->_name} = NULL; {rdelim}
    {rdelim}
    {include file="entity-aspect-after.tpl"}
		return ${$attribute->_name} && !$isNULL ? $this->add{$attribute->getMethodName()}(${$attribute->_name}, $appendDirty) : FALSE;
{else}



{if $attribute->_lazyLoad || $attribute->_lazyLoadExclusive}
		if ($appendDirty) {ldelim}
			$this->get{$attribute->getMethodName()}();
		{rdelim}
{/if}
{if $attribute->_nullDbEmptyStr}
		if (${$attribute->_name} === '') {ldelim}
			${$attribute->_name} = NULL;
		{rdelim}
{/if}
{if $attribute->_setConvert}
{foreach from=$attribute->_setConvert item=func}
    if ($appendDirty) {ldelim} ${$attribute->_name} =& {$func}(${$attribute->_name}); {rdelim}
{/foreach}
{/if}
{if $attribute->_syncAttributes}
    if ($appendDirty) {ldelim} 
{foreach from=$attribute->_syncAttributes item=attr}
      $this->setAttribute('{$attr}', ${$attribute->_name});
{/foreach}
    {rdelim}
{/if}
		$rb =& {$className}::getEntityResources();
{if $attribute->_isFile}
		// check if no file was uploaded
		if (is_array(${$attribute->_name}) && array_key_exists('size', ${$attribute->_name}) && ${$attribute->_name}['size'] <= 0) {ldelim}
			return FALSE;
		{rdelim}
    // check if attribute is file path
    if (${$attribute->_name} !== NULL && !SRA_FileAttribute::isValid(${$attribute->_name}) && is_scalar(${$attribute->_name}) && ($path = SRA_File::getRelativePath(NULL, ${$attribute->_name}))) {ldelim}
      ${$attribute->_name} =& SRA_FileAttribute::getInstanceFromUpload(array('tmp_name' => $path, 'name' => basename($path), 'size' => filesize($path), 'type' => SRA_File::getMimeType($path)), '{$attribute->_name}', $key, '{$entity->_name}', $this->getPrimaryKey(), '{$entity->_fileDir}', '{$entity->_fileDirUri}', '{$entity->_fileHandling}', '{$entity->_fileScriptRewrite}', '{$entity->_fileScriptUri}'{if $attribute->_fileProcessor}, '{$attribute->_fileProcessor}'{/if});
      if (SRA_FileAttribute::isValid(${$attribute->_name})) {ldelim} ${$attribute->_name}->getData(); {rdelim}
    {rdelim}
		// check if attribute is PHP $_FILES array element
		else if (${$attribute->_name} !== NULL && !SRA_FileAttribute::isValid(${$attribute->_name})) {ldelim}
{if $attribute->_fileHandling == $smarty.const.SRA_FILE_ATTRIBUTE_TYPE_DIR}
			if (!is_array(${$attribute->_name}) && !SRA_FileAttribute::isValid(${$attribute->_name} =& SRA_FileAttribute::getInstanceFromEncryptedId(${$attribute->_name}, '{$entity->_fileDir}'))) {ldelim}
				if (SRA_Error::isError(${$attribute->_name})) {ldelim}
					return $rb->getString('{$entity->_sysErrResource}');
				{rdelim}
				return FALSE;
			{rdelim}
			else {else}      {/if}if (is_array(${$attribute->_name}) && !SRA_FileAttribute::isValid(${$attribute->_name} =& SRA_FileAttribute::getInstanceFromUpload(${$attribute->_name}, '{$attribute->_name}', $key, '{$entity->_name}', $this->getPrimaryKey(), '{$entity->_fileDir}', '{$entity->_fileDirUri}', '{$entity->_fileHandling}', '{$entity->_fileScriptRewrite}', '{$entity->_fileScriptUri}'{if $attribute->_fileProcessor}, '{$attribute->_fileProcessor}'{/if}))) {ldelim}
				if (SRA_Error::isError(${$attribute->_name})) {ldelim}
					return $rb->getString('{$entity->_sysErrResource}');
				{rdelim}
				return FALSE;
			{rdelim}
			if (SRA_FileAttribute::isValid(${$attribute->_name})) {ldelim} ${$attribute->_name}->getData(); {rdelim}
		{rdelim}
    // set entity related attributes
    if (SRA_FileAttribute::isValid(${$attribute->_name})) {ldelim}
      ${$attribute->_name}->_setEntity('{$entity->_name}');
      ${$attribute->_name}->_setEntityId($this->getPrimaryKey());
      ${$attribute->_name}->_setAttribute('{$attribute->_name}');
			${$attribute->_name}->_setFileDir('{$entity->_fileDir}');
			${$attribute->_name}->_setFileDirUri('{$entity->_fileDirUri}');
			${$attribute->_name}->_setFileHandling('{$entity->_fileHandling}');
			${$attribute->_name}->_setFileScriptRewrite('{$entity->_fileScriptRewrite}');
			${$attribute->_name}->_setFileScriptUri('{$entity->_fileScriptUri}');
    {rdelim}
    
{if !$attribute->_cardinality && $attribute->_fileIconAttr && $entity->hasAttribute($attribute->_fileIconAttr)}
      // add icon for this file
      if (SRA_FileAttribute::isValid(${$attribute->_name})) {ldelim} $this->setAttribute('{$attribute->_fileIconAttr}', ${$attribute->_name}->getIcon('{$attribute->_fileIconDir}')); {rdelim}
{/if}


{if !$attribute->_cardinality && $attribute->_fileIndexAttr && $entity->hasAttribute($attribute->_fileIndexAttr)}
      // add search index for this file
      if (SRA_FileAttribute::isValid(${$attribute->_name})) {ldelim} $this->setAttribute('{$attribute->_fileIndexAttr}', ${$attribute->_name}->toText()); {rdelim}
{/if}


{if !$attribute->_cardinality && $attribute->_fileSizeAttr && $entity->hasAttribute($attribute->_fileSizeAttr)}
      // set size bytes attribute for this file
      if (SRA_FileAttribute::isValid(${$attribute->_name})) {ldelim} $this->setAttribute('{$attribute->_fileSizeAttr}', ${$attribute->_name}->getSize()); {rdelim}
{/if}
{if !$attribute->_cardinality && $attribute->_fileSizeKbAttr && $entity->hasAttribute($attribute->_fileSizeKbAttr)}
      // set size kilobytes attribute for this file
      if (SRA_FileAttribute::isValid(${$attribute->_name})) {ldelim} $this->setAttribute('{$attribute->_fileSizeKbAttr}', ${$attribute->_name}->getSizeKb()); {rdelim}
{/if}
{if !$attribute->_cardinality && $attribute->_fileSizeMbAttr && $entity->hasAttribute($attribute->_fileSizeMbAttr)}
      // set size megabytes attribute for this file
      if (SRA_FileAttribute::isValid(${$attribute->_name})) {ldelim} $this->setAttribute('{$attribute->_fileSizeMbAttr}', ${$attribute->_name}->getSizeMb()); {rdelim}
{/if}


{if $attribute->_fileUriAttr && $entity->hasAttribute($attribute->_fileUriAttr)}
      // set file uris to the {$attribute->_fileUriAttr} attribute
      $nl = NULL;
{if $attribute->_cardinality}
      if (is_array(${$attribute->_name})) {ldelim}
        $keys = array_keys(${$attribute->_name});
        foreach($keys as $key) {ldelim}
          $uris = array();
{/if}
      if ($appendDirty) {ldelim}
{if $attribute->_cardinality}
        $uris[] = SRA_FileAttribute::isValid(${$attribute->_name}[$key]) ? ${$attribute->_name}[$key]->getUri() : NULL;
{else}
        $this->setAttribute('{$attribute->_fileUriAttr}', SRA_FileAttribute::isValid(${$attribute->_name}) ? ${$attribute->_name}->getUri() : $nl);
{/if}
      {rdelim}
{if $attribute->_cardinality}
          $this->setAttribute('{$attribute->_fileUriAttr}', $uris);
        {rdelim}
      {rdelim}
{/if}
{/if}


{if !$attribute->_cardinality && $attribute->_thumbnails}
{foreach from=$attribute->_thumbnails key=tattr item=tconf}
      // add {$tattr} mapped thumbnail for this {$attribute->_name}
      if ($appendDirty && SRA_FileAttribute::isValid(${$attribute->_name})) {ldelim}
        $thumbnail = ${$attribute->_name}->toThumbnail({if $tconf->height}{$tconf->height}{else}NULL{/if}, {if $tconf->width}{$tconf->width}{else}NULL{/if}, '{$tconf->format}', {if $tconf->preserveAspect}TRUE{else}FALSE{/if}, {if $tconf->includeTypes}explode(' ', '{$tconf->includeTypes}'){else}NULL{/if}, {if $tconf->skipTypes}explode(' ', '{$tconf->skipTypes}'){else}NULL{/if});
{if $entity->hasCardinality($tattr)}
        if ($thumbnail && !is_array($thumbnail)) {ldelim} $thumbnail = array($thumbnail); {rdelim}
        $unlinkFiles = $thumbnail;
{if $tconf->attr}
        for($i=0; $i<count($thumbnail); $i++) {ldelim}
          require_once('{$entity->getAttrType($tattr)}{$entity->_voSuffix}.{$smarty.const.SRA_SYS_PHP_EXTENSION}');
          $thumbnail[$i] = new {$entity->getAttrType($tattr)}{$entity->_voSuffix}(array('{$tconf->attr}' => $thumbnail[$i]{if $tconf->attrPageNum}, '{$tconf->attrPageNum}' => $i+1{/if}));
        {rdelim}
{/if}
{else}
        if ($thumbnail && is_array($thumbnail)) {ldelim}
          for($i=1; $i<count($thumbnail); $i++) {ldelim}
            SRA_File::unlink($thumbnail[$i]);
          {rdelim}
          $thumbnail = $thumbnail[0];
        {rdelim}
        $unlinkFile = $thumbnail;
{if $tconf->attr}
        require_once('{$entity->getAttrType($tattr)}{$entity->_voSuffix}.{$smarty.const.SRA_SYS_PHP_EXTENSION}');
        $thumbnail = new {$entity->getAttrType($tattr)}{$entity->_voSuffix}(array('{$tconf->attr}' => $thumbnail{if $tconf->attrPageNum}, '{$tconf->attrPageNum}' => 1{/if}));
{/if}
{/if}
        $this->setAttribute('{$tattr}', $thumbnail);
{if $entity->hasCardinality($tattr)}
        for($i=0; $i<count($unlinkFiles); $i++) {ldelim}
          SRA_File::unlink($unlinkFiles[$i]);
        {rdelim}
{else}
        if (file_exists($unlinkFile)) {ldelim} SRA_File::unlink($unlinkFile); {rdelim}
{/if}
      {rdelim}
      else if ($appendDirty && ${$attribute->_name} == NULL) {ldelim}
        $nl = NULL;
        $this->setAttribute('{$tattr}', $nl);
      {rdelim}
{/foreach}
{/if} {* if $attribute->_thumbnails *}

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


{if $attribute->isEntity() && $entity->attrIsPersistent($attribute->_name) && !$attribute->getMappedAttributes()}
		// circular reference
		if (${$attribute->_name} === SRA_ENTITY_ATTRIBUTE_CIRC_REF) {ldelim}
			$this->_{$attribute->_name} = SRA_ENTITY_ATTRIBUTE_CIRC_REF;
		{rdelim}
		//validate type
		else if (!{$attribute->_type}{$entity->_voSuffix}::isValid(${$attribute->_name})) {ldelim}
			// try to lookup
			if (${$attribute->_name} && is_scalar(${$attribute->_name})) {ldelim}
				$dao =& SRA_DaoFactory::getDao('{$attribute->_type}');
				if (SRA_Error::isError(${$attribute->_name} =& $dao->findByPk(${$attribute->_name}))) {ldelim}
					return $rb->getString('{$attribute->_typeErrResource}');
				{rdelim}
			{rdelim}
			else if (!${$attribute->_name}) {ldelim}
				${$attribute->_name} = NULL;
			{rdelim}
			else {ldelim}
				return $rb->getString('{$attribute->_typeErrResource}');
			{rdelim}
		{rdelim}
{/if}

{if $attribute->_type eq $smarty.const.SRA_DATA_TYPE_DATE || $attribute->_type eq $smarty.const.SRA_DATA_TYPE_TIME}
		// convert to SRA_GregorianDate where necessary
		if (!SRA_GregorianDate::isValid(${$attribute->_name}) && ${$attribute->_name}) {ldelim}
			${$attribute->_name} = new SRA_GregorianDate(${$attribute->_name});
		{rdelim}
{if $attribute->_dateFormat}
    if (SRA_GregorianDate::isValid(${$attribute->_name})) {ldelim}
      ${$attribute->_name}->toStringFormat = '{$attribute->_dateFormat}';
    {rdelim}
{/if}
    if (SRA_GregorianDate::isValid(${$attribute->_name}) && ${$attribute->_name}->isDateOnly() != {if $attribute->_type eq $smarty.const.SRA_DATA_TYPE_DATE}TRUE{else}FALSE{/if}) {ldelim} ${$attribute->_name}->setDateOnly({if $attribute->_type eq $smarty.const.SRA_DATA_TYPE_DATE}TRUE{else}FALSE{/if}); {rdelim}
{/if}

{if $attribute->_type eq $smarty.const.SRA_DATA_TYPE_BOOLEAN}
    // convert boolean values
    ${$attribute->_name} = ${$attribute->_name} !== NULL ? SRA_Util::convertBoolean(${$attribute->_name}) : NULL;
{/if}

		if ($appendDirty && ((!$this->_{$attribute->_name} && !${$attribute->_name} && !$this->recordExists) || !SRA_Util::equal(${$attribute->_name}, $this->_{$attribute->_name}))) {ldelim}
			$this->setDirty('{$attribute->_name}');
			$this->_dirty['{$attribute->_name}'][] ={if $attribute->_useReference}&{/if} ${$attribute->_name};
      $ret = TRUE;
		{rdelim}

		$this->_setAttrs['{$attribute->_name}'] = TRUE;
{if !$attribute->_cardinality && $attribute->isEntity() && $attribute->_onRemoveDelete}
    if ($appendDirty && {$attribute->_type}{$entity->_voSuffix}::isValid($this->_{$attribute->_name}) && (${$attribute->_name} == NULL || !SRA_Util::equals($this->_{$attribute->_name}, ${$attribute->_name}))) {ldelim}
      if (!isset($this->_dirty['{$attribute->_name}'])) {ldelim}
        $this->_dirty['{$attribute->_name}'] = array();
      {rdelim}
      if (!isset($this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY])) {ldelim}
        $this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY] = array();
      {rdelim}
      $this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY][] = $this->_{$attribute->_name};
    {rdelim}
    if ($appendDirty && {$attribute->_type}{$entity->_voSuffix}::isValid(${$attribute->_name}) && isset($this->_dirty['{$attribute->_name}']) && isset($this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY])) {ldelim}
      $keys = array_keys($this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY]);
      foreach($keys as $key) {ldelim}
        if (SRA_Util::equals($this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY][$key], ${$attribute->_name})) {ldelim}
          unset($this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY][$key]);
        {rdelim}
      {rdelim}
      if (!count($this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY])) {ldelim} unset($this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY]); {rdelim}
    {rdelim}
{/if}
		$this->_{$attribute->_name} = ${$attribute->_name};
    {include file="entity-aspect-after.tpl"}
    return $ret;
{/if}

	{rdelim}
	// {rdelim}{rdelim}{rdelim}


{if $attribute->getAggregateAttributes()}
    // mapped setters for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{assign var="methodName" value="set"|cat:$attr->getMethodName()}
	// {ldelim}{ldelim}{ldelim} {$methodName}
	/**
	 * setter for <code>_{$attribute->_name}.{$attr->_name}</code>
	 * {if $attr->_apiResource}{$resources->getString($attr->_apiResource)}{/if} 
	 * 
   * @param $clean whether or not to return the non-dirty value for the attribute
	 * @return {if $attr->_isFile}SRA_FileAttribute{else}{$attr->_type}{/if}

	 * @access public
	 */
	function{if $attr->_useReference} &{/if} {$methodName}({if $attr->_useReference}& {/if}${$attr->_name}, $appendDirty = TRUE) {ldelim}
    {$Template->assign('aopMethodName', $methodName)}
    {include file="entity-aspect-before.tpl"}
    if (!{$attribute->_type}{$entity->_voSuffix}::isValid($this->get{$attribute->getMethodName()}())) {ldelim}
      $this->set{$attribute->getMethodName(0, 1)}(new {$attribute->_type}{$entity->_voSuffix}());
    {rdelim}
    $ret = $this->_{$attribute->_name}->set{$attr->getMethodName(0, 1)}(${$attr->_name}, $appendDirty);
    {include file="entity-aspect-after.tpl"}
    return $ret;
  {rdelim}
{/foreach}
{/if}
{/foreach}


{if !$entity->_skipPersistence && !$entity->_customDao}
	// {ldelim}{ldelim}{ldelim} setColumnValue
	/**
	 * used to set an attribute value using the table and column names as the 
	 * identifiers of that attribute
	 * 
	 * @param string $column the column name. this parameter is mandatory
	 * @param mixed $value the value to set
	 * @param string $table the table name. this parameter is optional. if not 
	 * specified, the primary table for this entity {$primaryTable->getName()} will 
	 * be used
	 * @param boolean $appendDirty whether or not the _dirty attribute should be 
	 * appended to reflect changes made
	 * @return TRUE on success, FALSE otherwise
	 * @access public
	 */
	function setColumnValue($column, $value, $table=FALSE, $appendDirty = TRUE) {ldelim}
    {$Template->assign('aopMethodName', "setColumnValue")}
    {include file="entity-aspect-before.tpl"}
    $ret = FALSE;
{foreach from=$schema->getTables() item=table}
{foreach from=$table->getColumns() item=column}
{if $column->isWritable() && $column->getBaseAttribute() neq $primaryKey->_name}
		if (({if $primaryTable->getName() == $table->getName()}!$table || {/if}$table == '{$table->getName()}') && $column == '{$column->getName()}') {ldelim}
			$ret = !$this->setAttribute('{$column->getBaseAttribute()}', is_object($value) && method_exists($value, 'getPrimaryKey') && SRA_EntityModeler::isValidType($this->getAttributeType('{$column->getBaseAttribute()}')) ? $value->getPrimaryKey() : $value);
		{rdelim}
{/if}
{/foreach}
{/foreach}
    {include file="entity-aspect-after.tpl"}
		return $ret;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
{/if}


	//*** ADDERS ***//
	// {ldelim}{ldelim}{ldelim} addAttribute
	/**
	 * adds to an attribute
	 * 
	 * @param string $name the name of the attribute to add to
	 * @param mixed $val the value to add
	 * @param boolean $appendDirty whether or not the _dirty attribute should be 
	 * appended to reflect changes made
	 * @return the return value from the setter
	 * @access public
	 */
	function addAttribute($name, $val, $appendDirty = TRUE) {ldelim}
    {$Template->assign('aopMethodName', "addAttribute")}
    {include file="entity-aspect-before.tpl"}
{foreach from=$entity->getAttributes() item=attribute}
{if !$attribute->_readOnly && $attribute->_cardinality}
		if ('{$attribute->_name}' == $name) {ldelim}
      {include file="entity-aspect-after.tpl"}
			return $this->add{$attribute->getMethodName()}($val, $appendDirty);
		{rdelim}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
		return FALSE;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_cardinality}
{assign var="methodName" value="add"|cat:$attribute->getMethodName()}
	// {ldelim}{ldelim}{ldelim} {$methodName}
	/**
	 * Add setter for <code>_{$attribute->_name}</code>. Implicitely called by 
	 * this attributes setter method. returns the # of values that were dirty 
   * added (or FALSE/error string for errors)
	 * {if $attribute->_apiResource}{$resources->getString($attribute->_apiResource)}{/if} 
	 * 
	 * @param {$attribute->_type} ${$attribute->_name} the value to add. this may 
	 * be either a single {if $attribute->_isFile}SRA_FileAttribute or PHP $_FILE array element{else}{$attribute->_type}{/if} or an array of thos types
	 * @param boolean $appendDirty whether or not the _dirty attribute should be 
	 * appended to reflect changes made
	 * @return int
	 * @access public
	 */
	function {$methodName}( {if $attribute->_useReference}& {/if}${$attribute->_name}, $appendDirty = TRUE ) {ldelim}
    {$Template->assign('aopMethodName', $methodName)}
    {include file="entity-aspect-before.tpl"}
    $added = 0;
{if $attribute->_matchUserId}
    if (!$this->_matchUserId('{$attribute->_matchUserId}', 'get{$attribute->getMethodName()}')) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return FALSE;
    {rdelim}
{/if}
{if $attribute->_readOnly}
    // this attribute is read-only and cannot be modified
    if ($appendDirty) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return FALSE;
    {rdelim}
{/if}

{if !$attribute->_isFile && ($attribute->_lazyLoad || $attribute->_lazyLoadExclusive) && $attribute->_cardinalityUpper != $smarty.const.SRA_MAX_INT_VAL}
		if ($appendDirty) {ldelim}
			$this->get{$attribute->getMethodName()}();
		{rdelim}
{/if}
{if $attribute->_isFile}
    $this->get{$attribute->getMethodName()}();
{/if}
    
		$keys = is_array(${$attribute->_name}) ? array_keys(${$attribute->_name}) : array(NULL);

		$rb =& {$className}::getEntityResources();
		foreach ($keys as $key) {ldelim}
      if (is_array(${$attribute->_name})) {ldelim}
        $add =& ${$attribute->_name}[$key];
      {rdelim}
      else {ldelim}
        $add =& ${$attribute->_name};
      {rdelim}
{if $attribute->_nullDbEmptyStr}
      if ($add === '') {ldelim}
        $add = NULL;
        if (is_array(${$attribute->_name})) {ldelim}
          ${$attribute->_name}[$key] =& $add;
        {rdelim}
        else {ldelim}
          ${$attribute->_name} =& $add;
        {rdelim}
      {rdelim}
{/if}
{if $attribute->_setConvert}
      if ($appendDirty) {ldelim}
{foreach from=$attribute->_setConvert item=func}
        $add =& {$func}($add);
{/foreach}
        if (is_array(${$attribute->_name})) {ldelim}
          ${$attribute->_name}[$key] =& $add;
        {rdelim}
        else {ldelim}
          ${$attribute->_name} =& $add;
        {rdelim}
      {rdelim}
{/if}
{if $attribute->_syncAttributes}
      if ($appendDirty) {ldelim}
{foreach from=$attribute->_syncAttributes item=attr}
        $this->addAttribute('{$attr}', $add);
{/foreach}
      {rdelim}
{/if}
{if $attribute->_isFile}
      // check if no file was uploaded
      if (is_array($add) && array_key_exists('size', $add) && $add['size'] <= 0) {ldelim}
        continue;
      {rdelim}
      // check if attribute is file path
      if ($add !== NULL && !SRA_FileAttribute::isValid($add) && is_scalar($add) && ($path = SRA_File::getRelativePath(NULL, $add))) {ldelim}
        $add =& SRA_FileAttribute::getInstanceFromUpload(array('tmp_name' => $path, 'name' => basename($path), 'size' => filesize($path), 'type' => SRA_File::getMimeType($path)), '{$attribute->_name}', $key, '{$entity->_name}', $this->getPrimaryKey(), '{$entity->_fileDir}', '{$entity->_fileDirUri}', '{$entity->_fileHandling}', '{$entity->_fileScriptRewrite}', '{$entity->_fileScriptUri}'{if $attribute->_fileProcessor}, '{$attribute->_fileProcessor}'{/if});
        if (SRA_FileAttribute::isValid($add)) {ldelim} $add->getData(); {rdelim}
      {rdelim}
      // check if attribute is PHP $_FILES array element
      else if ($add !== NULL && !SRA_FileAttribute::isValid($add)) {ldelim}
				if (!is_array($add) && !SRA_FileAttribute::isValid($add =& SRA_FileAttribute::getInstanceFromEncryptedId($add, '{$entity->_fileDir}'))) {ldelim}
					if (SRA_Error::isError($add)) {ldelim}
            {include file="entity-aspect-after.tpl"}
						return $rb->getString('{$entity->_sysErrResource}');
					{rdelim}
					return FALSE;
				{rdelim}
				else if (is_array($add) && !SRA_FileAttribute::isValid($add =& SRA_FileAttribute::getInstanceFromUpload($add, '{$attribute->_name}', $key, '{$entity->_name}', $this->getPrimaryKey(), '{$entity->_fileDir}', '{$entity->_fileDirUri}', '{$entity->_fileHandling}', '{$entity->_fileScriptRewrite}', '{$entity->_fileScriptUri}'))) {ldelim}
					if (SRA_Error::isError($add)) {ldelim}
            {include file="entity-aspect-after.tpl"}
						return $rb->getString('{$entity->_sysErrResource}');
					{rdelim}
          {include file="entity-aspect-after.tpl"}
					return FALSE;
				{rdelim}
				if (SRA_FileAttribute::isValid($add)) {ldelim} $add->getData(); {rdelim}
			{rdelim}
      if (is_array(${$attribute->_name}) && !SRA_FileAttribute::isValid(${$attribute->_name}[$key]) && SRA_FileAttribute::isValid($add)) {ldelim}
        ${$attribute->_name}[$key] =& $add;
      {rdelim}
      else if (!is_array(${$attribute->_name}) && !SRA_FileAttribute::isValid(${$attribute->_name}) && SRA_FileAttribute::isValid($add)) {ldelim}
        ${$attribute->_name} =& $add;
      {rdelim}
      if ((is_array(${$attribute->_name}) && !SRA_FileAttribute::isValid(${$attribute->_name}[$key])) || (!is_array(${$attribute->_name}) && !SRA_FileAttribute::isValid(${$attribute->_name}))) {ldelim} continue; {rdelim}
      // set entity related attributes
      if (is_array(${$attribute->_name})) {ldelim}
        ${$attribute->_name}[$key]->_setEntity('{$entity->_name}');
        ${$attribute->_name}[$key]->_setEntityId($this->getPrimaryKey());
        ${$attribute->_name}[$key]->_setAttribute('{$attribute->_name}');
        ${$attribute->_name}[$key]->_setAttributeIndex(count($this->_{$attribute->_name}));
        ${$attribute->_name}[$key]->_setFileDir('{$entity->_fileDir}');
        ${$attribute->_name}[$key]->_setFileDirUri('{$entity->_fileDirUri}');
        ${$attribute->_name}[$key]->_setFileHandling('{$entity->_fileHandling}');
        ${$attribute->_name}[$key]->_setFileScriptRewrite('{$entity->_fileScriptRewrite}');
        ${$attribute->_name}[$key]->_setFileScriptUri('{$entity->_fileScriptUri}');
      {rdelim}
      else {ldelim}
        ${$attribute->_name}->_setEntity('{$entity->_name}');
        ${$attribute->_name}->_setEntityId($this->getPrimaryKey());
        ${$attribute->_name}->_setAttribute('{$attribute->_name}');
        ${$attribute->_name}->_setAttributeIndex(0);
        ${$attribute->_name}->_setFileDir('{$entity->_fileDir}');
        ${$attribute->_name}->_setFileDirUri('{$entity->_fileDirUri}');
        ${$attribute->_name}->_setFileHandling('{$entity->_fileHandling}');
        ${$attribute->_name}->_setFileScriptRewrite('{$entity->_fileScriptRewrite}');
        ${$attribute->_name}->_setFileScriptUri('{$entity->_fileScriptUri}');
      {rdelim}
{/if}

{if $attribute->_type eq $smarty.const.SRA_DATA_TYPE_DATE || $attribute->_type eq $smarty.const.SRA_DATA_TYPE_TIME}
		// convert to SRA_GregorianDate where necessary
		if (!SRA_GregorianDate::isValid($add) && $add) {ldelim}
			$add = new SRA_GregorianDate($add);
      is_array(${$attribute->_name}) ? ${$attribute->_name}[$key] =& $add : ${$attribute->_name} =& $add;
		{rdelim}
{if $attribute->_dateFormat}
    if (SRA_GregorianDate::isValid($add)) {ldelim}
      $add->toStringFormat = '{$attribute->_dateFormat}';
    {rdelim}
{/if}
    if (SRA_GregorianDate::isValid($add) && $add->isDateOnly() != {if $attribute->_type eq $smarty.const.SRA_DATA_TYPE_DATE}TRUE{else}FALSE{/if}) {ldelim} $add->setDateOnly({if $attribute->_type eq $smarty.const.SRA_DATA_TYPE_DATE}TRUE{else}FALSE{/if}); {rdelim}
{/if}

{if $attribute->isEntity() && $entity->attrIsPersistent($attribute->_name)}
			//validate type
			if (!{$attribute->_type}{$entity->_voSuffix}::isValid($add)) {ldelim}
				// try to lookup
				if (is_scalar($add)) {ldelim}
					$dao =& SRA_DaoFactory::getDao('{$attribute->_type}');
					if (SRA_Error::isError($add =& $dao->findByPk($add))) {ldelim}
            {include file="entity-aspect-after.tpl"}
						return $rb->getString('{$attribute->_typeErrResource}');
					{rdelim}
          else {ldelim}
            is_array(${$attribute->_name}) ? ${$attribute->_name}[$key] =& $add : ${$attribute->_name} =& $add;
          {rdelim}
				{rdelim}
				else {ldelim}
          {include file="entity-aspect-after.tpl"}
					return $rb->getString('{$attribute->_typeErrResource}');
				{rdelim}
			{rdelim}
{/if}

{if $attribute->_recursiveLink || $attribute->_unionLink}
      if (isset($this->_linkedAttributes['{$attribute->_name}']) && {if $attribute->isEntity()}isset($this->_linkedAttributes['{$attribute->_name}'][$add->getPrimaryKey()]){else}in_array($add, $this->_linkedAttributes['{$attribute->_name}']){/if}) {ldelim}
{if $attribute->isEntity()}
        unset($this->_linkedAttributes['{$attribute->_name}'][$add->getPrimaryKey()]);
{else}
        unset($this->_linkedAttributes['{$attribute->_name}'][array_search($add, $this->_linkedAttributes['{$attribute->_name}'])]);
{/if}
      {rdelim}
{/if}

			if ({if $attribute->_cardinalityUpper != $smarty.const.SRA_MAX_INT_VAL}count($this->_{$attribute->_name}) < {$attribute->_cardinalityUpper}{if $attribute->isEntity()} || $this->get{$attribute->getMethodName()}($add->getPrimaryKey(TRUE)){/if}{else}TRUE{/if}) {ldelim}
{if $attribute->isEntity()}
					if ((!$appendDirty || !$add->getPrimaryKey(TRUE) || $add->isDirty() || !$this->get{$attribute->getMethodName()}($add->getPrimaryKey(TRUE))) && (!$this->recordExists || !isset($this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY][$add->getPrimaryKey(TRUE)]))) {ldelim}
            if (isset($this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY][$add->getPrimaryKey(TRUE)])) {ldelim} unset($this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY][$add->getPrimaryKey(TRUE)]); {rdelim}
{/if}
          $duplicate = {if $attribute->isEntity()}$add->getPrimaryKey(TRUE) && {/if}{if $attribute->isEntity()}$this->get{$attribute->getMethodName()}($add->getPrimaryKey(TRUE)){else}in_array($add, $this->_{$attribute->_name}){/if};
          $addDirty = {if $attribute->isEntity() && $entity->attrIsPersistent($attribute->_name)}!$add->getPrimaryKey(TRUE) || {/if}($appendDirty && !$duplicate);
{if $attribute->_cardinalityUnique}
          // enforce unique values for this attribute
          if (!$duplicate) {ldelim}
{/if}
          if (is_array(${$attribute->_name})) {ldelim}
            $this->_{$attribute->_name}[{if $attribute->isEntity()}$add->getPrimaryKey(TRUE) ? $add->getPrimaryKey(TRUE) : count($this->_{$attribute->_name}){/if}] ={if $attribute->_useReference}&{/if} ${$attribute->_name}[$key];
          {rdelim}
          else {ldelim}
            $this->_{$attribute->_name}[{if $attribute->isEntity()}$add->getPrimaryKey(TRUE) ? $add->getPrimaryKey(TRUE) : count($this->_{$attribute->_name}){/if}] ={if $attribute->_useReference}&{/if} ${$attribute->_name};
          {rdelim}
{if $attribute->_lazyLoad}
{if $attribute->isEntity()}
          if ($add->getPrimaryKey(TRUE)) {ldelim}
{/if}
          if (is_array(${$attribute->_name})) {ldelim}
            $this->_lazyLoaded['{$attribute->_name}'{if $attribute->isEntity()} . $add->getPrimaryKey(TRUE){/if}] ={if $attribute->_useReference}&{/if} ${$attribute->_name}[$key];
          {rdelim}
          else {ldelim}
            $this->_lazyLoaded['{$attribute->_name}'{if $attribute->isEntity()} . $add->getPrimaryKey(TRUE){/if}] ={if $attribute->_useReference}&{/if} ${$attribute->_name};
          {rdelim}
{if $attribute->isEntity()}
          {rdelim}
{/if}
{/if}
					if ($addDirty) {ldelim}
            $added++;
						$this->setDirtyAdd('{$attribute->_name}');
            if (is_array(${$attribute->_name})) {ldelim}
						  $this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_ADD_DIRTY_KEY][{if $attribute->isEntity()}$add->getPrimaryKey(TRUE) ? $add->getPrimaryKey(TRUE) : count($this->_{$attribute->_name}){/if}] =& ${$attribute->_name}[$key];
            {rdelim}
            else {ldelim}
              $this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_ADD_DIRTY_KEY][{if $attribute->isEntity()}$add->getPrimaryKey(TRUE) ? $add->getPrimaryKey(TRUE) : count($this->_{$attribute->_name}){/if}] =& ${$attribute->_name};
            {rdelim}
					{rdelim}
{if $attribute->_cardinalityUnique}
          {rdelim}
{/if}
{if $attribute->isEntity()}
					{rdelim}
{/if}
			{rdelim}
			else {ldelim}
				$rb =& {$className}::getEntityResources();
        {include file="entity-aspect-after.tpl"}
				return $rb->getString('{$attribute->_cardinalityErr}');
			{rdelim}
		{rdelim}
		$this->_setAttrs['{$attribute->_name}'] = TRUE;
    
    {include file="entity-aspect-after.tpl"}
    
    return $added;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
{/if}

{if $attribute->getAggregateAttributes()}
    // mapped adders for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{if !$attr->_readOnly && $attr->_cardinality}
{assign var="methodName" value="add"|cat:$attr->getMethodName()}
	// {ldelim}{ldelim}{ldelim} {$methodName}
	/**
	 * adder for <code>_{$attribute->_name}.{$attr->_name}</code>
	 * {if $attr->_apiResource}{$resources->getString($attr->_apiResource)}{/if} 
	 * 
   * @param $clean whether or not to return the non-dirty value for the attribute
	 * @return int

	 * @access public
	 */
	function{if $attr->_useReference} &{/if} {$methodName}({if $attr->_useReference}& {/if}${$attr->_name}, $appendDirty = TRUE) {ldelim}
    {$Template->assign('aopMethodName', $methodName)}
    {include file="entity-aspect-before.tpl"}
    if (!{$attribute->_type}{$entity->_voSuffix}::isValid($this->get{$attribute->getMethodName()}())) {ldelim}
      $this->set{$attribute->getMethodName()}(new {$attribute->_type}{$entity->_voSuffix}(array()));
    {rdelim}
    $ret = $this->_{$attribute->_name}->add{$attr->getMethodName(0, 1)}(${$attr->_name}, $appendDirty);
    {include file="entity-aspect-after.tpl"}
    return $ret;
  {rdelim}
{/if}
{/foreach}
{/if}

{/foreach}


	//*** REMOVERS ***//
	// {ldelim}{ldelim}{ldelim} removeAttribute
	/**
	 * removes from an attribute
	 * 
	 * @param string $name the name of the attribute to remove from
	 * @param mixed $val the value to remove
	 * @param boolean $appendDirty whether or not the _dirty attribute should be 
	 * appended to reflect changes made
	 * @return the return value from the remover
	 * @access public
	 */
	function removeAttribute($name, $val, $appendDirty = TRUE) {ldelim}
    {$Template->assign('aopMethodName', "removeAttribute")}
    {include file="entity-aspect-before.tpl"}
{foreach from=$entity->getAttributes() item=attribute}
{if !$attribute->_readOnly && $attribute->_cardinality}
		if ('{$attribute->_name}' == $name) {ldelim}
      {include file="entity-aspect-after.tpl"}
			return $this->remove{$attribute->getMethodName()}($val, $appendDirty);
		{rdelim}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
		return FALSE;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
{foreach from=$entity->getAttributes() item=attribute}
{if !$attribute->_readOnly && $attribute->_cardinality}
{assign var="methodName" value="remove"|cat:$attribute->getMethodName()}
	// {ldelim}{ldelim}{ldelim} {$methodName}
	/**
	 * Remove method for <code>_{$attribute->_name}</code>
	 * {if $attribute->_apiResource}{$resources->getString($attribute->_apiResource)}{/if} 
	 * 
	 * @param {if $attribute->_isFile}SRA_FileAttribute or PHP $_FILES array element or URI identifier for the file{else}{$attribute->_type}{/if} ${$attribute->_name} the value to remove. this may 
	 * be either a single value or an array of those types
	 * @param boolean $appendDirty whether or not the _dirty attribute should be 
	 * appended to reflect changes made
	 * @return The # of {$attribute->_type} removed
	 * @access public
	 */
	function {$methodName}( {if $attribute->_useReference}& {/if}${$attribute->_name}, $appendDirty = TRUE ) {ldelim}
    {$Template->assign('aopMethodName', $methodName)}
    {include file="entity-aspect-before.tpl"}
    
{if $attribute->_matchUserId}
    if (!$this->_matchUserId('{$attribute->_matchUserId}', 'get{$attribute->getMethodName()}')) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return FALSE;
    {rdelim}
{/if}
{if $attribute->_readOnly}
    // this attribute is read-only and cannot be modified
    if ($appendDirty) {ldelim}
      {include file="entity-aspect-after.tpl"}
      return FALSE;
    {rdelim}
{/if}

		if (!is_array(${$attribute->_name})) {ldelim}
			${$attribute->_name} = array(${$attribute->_name});
		{rdelim}
    $keys = array_keys(${$attribute->_name});
{if $attribute->isEntity()}
    foreach ($keys as $key) {ldelim}
      // validate removal objects
      if (is_scalar(${$attribute->_name}[$key])) {ldelim}
        ${$attribute->_name}[$key] =& $this->get{$attribute->getMethodName()}(${$attribute->_name}[$key]);
      {rdelim}
      // cannot remove because it is not present
      if (!{$attribute->_type}{$entity->_voSuffix}::isValid(${$attribute->_name}[$key])) {ldelim}
        unset(${$attribute->_name}[$key]);
      {rdelim}
    {rdelim}
    $keys = array_keys(${$attribute->_name});
{/if}
		
		$removed = 0;
		foreach ($keys as $key) {ldelim}
{if $attribute->_syncAttributes}
      if ($appendDirty) {ldelim}
{foreach from=$attribute->_syncAttributes item=attr}
        $this->removeAttribute('{$attr}', ${$attribute->_name}[$key]);
{/foreach}
      {rdelim}
{/if}
{if !$attribute->isEntity()}
			$idx = -1;
      $this->get{$attribute->getMethodName()}();
      $akeys = array_keys($this->_{$attribute->_name});
			for($i=count($akeys) - 1; $i>= 0; $i--) {ldelim}
				if ($this->_{$attribute->_name}[$akeys[$i]] == ${$attribute->_name}[$key]) {ldelim}
					$idx = $akeys[$i];
					if ($idx != -1) {ldelim}
            unset($this->_{$attribute->_name}[$akeys[$i]]);
          {rdelim}
				{rdelim}
			{rdelim}
{/if}
			if ({if $attribute->isEntity()}$this->get{$attribute->getMethodName()}(${$attribute->_name}[$key]->getPrimaryKey(TRUE)){else}$idx>=0{/if}) {ldelim}
				if ($appendDirty) {ldelim}
					$this->setDirtyRemove('{$attribute->_name}');
					$this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY][{if $attribute->isEntity()}${$attribute->_name}[$key]->getPrimaryKey(TRUE){/if}] ={if $attribute->_useReference}&{/if} ${$attribute->_name}[$key];
				{rdelim}
				unset($this->_{$attribute->_name}[{if $attribute->isEntity()}${$attribute->_name}[$key]->getPrimaryKey(TRUE){else}$idx{/if}]);
				$removed++;
			{rdelim}
{if $attribute->isEntity()}
      else if (!${$attribute->_name}[$key]->getPrimaryKey(TRUE) && isset($this->_{$attribute->_name}[${$attribute->_name}[$key]->getPrimaryKey(TRUE)])) {ldelim}
        unset($this->_{$attribute->_name}[${$attribute->_name}[$key]->getPrimaryKey(TRUE)]);
      {rdelim}
{/if}
		{rdelim}
    {include file="entity-aspect-after.tpl"}
		return $removed;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
{/if}

{if $attribute->getAggregateAttributes()}
    // mapped removers for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
{if !$attr->_readOnly && $attr->_cardinality}
{assign var="methodName" value="remove"|cat:$attr->getMethodName()}
	// {ldelim}{ldelim}{ldelim} {$methodName}
	/**
	 * remover for <code>_{$attribute->_name}.{$attr->_name}</code>
	 * {if $attr->_apiResource}{$resources->getString($attr->_apiResource)}{/if} 
	 * 
   * @param $clean whether or not to return the non-dirty value for the attribute
	 * @return The # of {$attr->_type} removed
	 * @access public
	 */
	function {$methodName}({if $attr->_useReference}& {/if}${$attr->_name}, $appendDirty = TRUE) {ldelim}
    {$Template->assign('aopMethodName', $methodName)}
    {include file="entity-aspect-before.tpl"}
    if (!{$attribute->_type}{$entity->_voSuffix}::isValid($this->get{$attribute->getMethodName()}())) {ldelim}
      $this->set{$attribute->getMethodName()}(new {$attribute->_type}{$entity->_voSuffix}(array()));
    {rdelim}
    $ret = $this->_{$attribute->_name}->remove{$attr->getMethodName(0, 1)}(${$attr->_name}, $appendDirty);
    {include file="entity-aspect-after.tpl"}
    return $ret;
  {rdelim}
{/if}
{/foreach}
{/if}

{/foreach}


	// {ldelim}{ldelim}{ldelim} resetAttribute
	/**
	 * Resets the $attr to its original value if it is dirty
   * @param $attr the attribute to restore
   * @access public
	 * @return boolean
	 */
	function resetAttribute($attr) {ldelim}
    {$Template->assign('aopMethodName', "resetAttribute")}
    {include file="entity-aspect-before.tpl"}
    $ret = FALSE;
    if (isset($this->_dirty[$attr])) {ldelim}
      if (isset($this->_clean[$attr])) {ldelim}
        $this->setAttribute($attr, $this->_clean[$attr]);
        unset($this->_clean[$attr]);
      {rdelim}
      else {ldelim}
        $this->setAttribute($attr, $var = NULL);
      {rdelim}
      unset($this->_dirty[$attr]);
      $ret = TRUE;
    {rdelim}
    {include file="entity-aspect-after.tpl"}
    return $ret;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}


	// {ldelim}{ldelim}{ldelim} resetDirtyFlags
	/**
	 * Resets all of the current dirty/modified flags for this value object. 
	 * usually called after all changes have been recorded
   * @param array $skip any dirty flags NOT to reset
   * @access public
	 * @return void
	 */
	function resetDirtyFlags($skip = NULL) {ldelim}
    {$Template->assign('aopMethodName', "resetDirtyFlags")}
    {include file="entity-aspect-before.tpl"}
    if ($skip) {ldelim}
      $keys = array_keys($this->_dirty);
      foreach($keys as $key) {ldelim}
        if (!in_array($key, $skip)) {ldelim} unset($this->_dirty[$key]); {rdelim}
      {rdelim}
    {rdelim}
    else {ldelim}
		  $this->_dirty = array();
    {rdelim}
    {include file="entity-aspect-after.tpl"}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// {ldelim}{ldelim}{ldelim} setDirty
	/**
	 * Used to create an undo/dirty/modified stack for a given attribute
	 *
	 * @param  string $attr the attribute to create the dirty array stack for
	 * @access	public
	 * @return	boolean
	 */
	function setDirty($attr) {ldelim}
    {$Template->assign('aopMethodName', "setDirty")}
    {include file="entity-aspect-before.tpl"}
    $ret = FALSE;
    if (!isset($this->_clean[$attr])) {ldelim}
      $this->_clean[$attr] = $this->getAttribute($attr);
    {rdelim}
		if (!isset($this->_dirty[$attr]) || !is_array($this->_dirty[$attr])) {ldelim}
			$this->_dirty[$attr] = array();
      $ret = TRUE;
		{rdelim}
    {include file="entity-aspect-after.tpl"}
    return $ret;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}


	// {ldelim}{ldelim}{ldelim} setDirtyAdd
	/**
	 * Used to add an array() to the ADD _dirty index for the $attribute specified
	 *
	 * @param  string $attr the name of the attribute to add the dirty 'ADD' index
	 * array for
	 * @access	public
	 * @return	TRUE on success, FALSE otherwise
	 */
	function setDirtyAdd($attr) {ldelim}
    {$Template->assign('aopMethodName', "setDirtyAdd")}
    {include file="entity-aspect-before.tpl"}
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_cardinality}
		if ('{$attribute->_name}' == $attr) {ldelim}
			if (!is_array($this->_dirty[$attr][SRA_ATTRIBUTE_ADD_DIRTY_KEY])) {ldelim}
				$this->_dirty[$attr][SRA_ATTRIBUTE_ADD_DIRTY_KEY] = array();
			{rdelim}
      {include file="entity-aspect-after.tpl"}
			return TRUE;
		{rdelim}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
{if $entity->_parentEntity}
		return parent::setDirtyAdd($attr);
{else}
		return FALSE;
{/if}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// {ldelim}{ldelim}{ldelim} setDirtyRemove
	/**
	 * Used to add an array() to the REMOVE _dirty index for the $attribute specified
	 *
	 * @param  string $attr the name of the attribute to add the dirty 'REMOVE' index
	 * array for
	 * @access	public
	 * @return	boolean
	 */
	function setDirtyRemove($attr) {ldelim}
    {$Template->assign('aopMethodName', "setDirtyRemove")}
    {include file="entity-aspect-before.tpl"}
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_cardinality}
		if ('{$attribute->_name}' == $attr) {ldelim}
			if (!is_array($this->_dirty[$attr][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY])) {ldelim}
				$this->_dirty[$attr][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY] = array();
			{rdelim}
      {include file="entity-aspect-after.tpl"}
			return TRUE;
		{rdelim}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
{if $entity->_parentEntity}
		return parent::setDirtyRemove($attr);
{else}
		return FALSE;
{/if}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}


	//*** VALIDATORS ***//
	// {ldelim}{ldelim}{ldelim} getEntityValidators
	/**
	 * returns an array of the names of the entity validators for this class or 
   * NULL if it does not have any defined
	 * @access public
	 * @return array
	 */
	function getEntityValidators() {ldelim}
    {$Template->assign('aopMethodName', "getEntityValidators")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
{if $entity->_validateGenerators}
{assign var=started value=0}
    return array({foreach from=$entity->_validateGenerators item=validator}{if $started}, {/if}'{$validator->_name}'{assign var=started value=1}{/foreach});
{else}
    return NULL;
{/if}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} isValidatorMandatory
	/**
	 * returns TRUE if $validator is mandatory. returns NULL if $validator is not 
   * valid
   * @param string $validator the identifier of the validator
	 * @access public
	 * @return boolean
	 */
	function isValidatorMandatory($validator) {ldelim}
    {$Template->assign('aopMethodName', "isValidatorMandatory")}
    {include file="entity-aspect-before.tpl"}
    $mandatory = NULL;
{if $entity->_validateGenerators}
    switch($validator) {ldelim}
{foreach from=$entity->_validateGenerators item=validator}
      case '{$validator->_name}':
        $mandatory = {if $validator->_mandatory}TRUE{else}FALSE{/if};
        break;
{/foreach}
    {rdelim}
{/if}
    {include file="entity-aspect-after.tpl"}
    return $mandatory;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} hasNonMandatoryValidator
	/**
	 * returns TRUE if this entity has any non-mandatory validators
	 * @access public
	 * @return boolean
	 */
	function hasNonMandatoryValidator() {ldelim}
    {$Template->assign('aopMethodName', "hasNonMandatoryValidator")}
    {include file="entity-aspect-before.tpl"}
{assign var=hasNonMandatoryValidator value=0}
{if $entity->_validateGenerators}
{foreach from=$entity->_validateGenerators item=validator}{if !$validator->_mandatory}{assign var=hasNonMandatoryValidator value=1}{/if}{/foreach}
{/if}
    return {if $hasNonMandatoryValidator}TRUE{else}FALSE{/if};
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} isAttributeRequired
	/**
	 * returns TRUE if $attr is required. returns NULL if $attr is not valid
   * @param string $attr the name of the attribute
   * @param boolean $excludeIfHasDefaultValue when TRUE, $attr will only be 
   * considered required if it is mandatory and does not have a default value
	 * @access public
	 * @return boolean
	 */
	function isAttributeRequired($attr, $excludeIfHasDefaultValue=FALSE) {ldelim}
    {$Template->assign('aopMethodName', "isAttributeRequired")}
    {include file="entity-aspect-before.tpl"}
    $required = NULL;
{foreach from=$entity->getAttributes() item=attribute}
    if ($attr == '{$attribute->_name}') $required = {if $attribute->isRequired()}{if $attribute->_hasDefault}!$excludeIfHasDefaultValue{else}TRUE{/if}{else}FALSE{/if};
{/foreach}
    {include file="entity-aspect-after.tpl"}
    return $required;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} validate
	/**
	 * Used to validate the state of this entity based on the attribute values 
	 * defined for it. Returns FALSE and sets errors messages in the attribute 
	 * validateErrors un validation failure.
	 * 
	 * @param string $_id the identifier of the validation to perform. this may be 
	 * either the name of an attribute to validate or the name of an entity 
	 * validation sequence (the "validate" element key in the entity model). if 
	 * not specified, all validation will be performed (both attribute and eneity)
	 * otherwise, only the validation specified will be performed. $_id may be an 
	 * array to identify multiple validations
	 * @param boolean $reset whether or not to reset the instance 'validateErrors'
   * attribute
   * @param boolean $evenIfNotDirty whether or not to validate regardless of 
   * whether or not the attribute is dirty. by default, only dirty attributes 
   * are validated
	 * @return TRUE for successful validation, FALSE otherwise
	 * @access public
	 */
	function validate($_id = FALSE, $reset = TRUE, $evenIfNotDirty = FALSE) {ldelim}
    {$Template->assign('aopMethodName', "validate")}
    {include file="entity-aspect-before.tpl"}
    require_once('model/SRA_AttributeValidator.php');
    
		if ($reset) {ldelim} $this->validateErrors = array(); {rdelim}
		$_id = $_id && !is_array($_id) ? array($_id) : $_id;
		$rb =& {$className}::getEntityResources();
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_validators || ($attribute->_cardinality && ($attribute->_cardinalityLower > 0 || $attribute->_cardinalityUpper != $smarty.const.SRA_MAX_INT_VAL))}
		if (($evenIfNotDirty || $this->isDirty('{$attribute->_name}'){if $attribute->isRequired()} || !$this->recordExists{/if}) && (!$_id || in_array('{$attribute->_name}', $_id))) {ldelim}
{if $attribute->_validators}
			// validate {$attribute->_name}
			$params = array('attr' => $rb->getString('{$attribute->getResourceName()}'), 'attribute'=> '{$attribute->_name}'{if $attribute->_vars}{foreach from=$attribute->_vars key=key item=item}, '{$key}' => '{$Template->strReplace("'", "\\'", $item)}' {/foreach}{/if});
			${$attribute->_name} ={if $attribute->_useReference || $attribute->_cardinality}& {/if}$this->get{if $attribute->_cardinality}AddedVals('{$attribute->_name}'){else}{$attribute->getMethodName()}(){/if};
{assign var=uniqueFound value=0}
{foreach from=$attribute->_validators item=validator}
{if $validator eq 'unique'}
{if !$uniqueFound}
      $params['object'] =& $this;
{/if}
{assign var=uniqueFound value=1}
{/if}
			if ({if $attribute->isRequired() && $validator neq 'required'}($evenIfNotDirty || $this->isDirty('{$attribute->_name}')) && {/if}{if $validator neq 'required'}{if $attribute->_cardinality}${$attribute->_name}{else}isset(${$attribute->_name}){/if} && {/if}!SRA_AttributeValidator::{$validator}(${$attribute->_name}, $params)) {ldelim}
{if $attribute->_isFile}
				if (${$attribute->_name}) {ldelim} ${$attribute->_name}->delete(); {rdelim}
        $this->resetAttribute('{$attribute->_name}');
{/if}
				$this->validateErrors['{$attribute->_name}'] = $rb->getString('{$attribute->_msgs[$validator]}', $params);
			{rdelim}
{/foreach}
{/if}
{if $attribute->_cardinality && $attribute->_cardinalityLower > 0}
      // validate lower bound of cardinality
      if ((!$this->recordExists || (isset($this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY]) && count($this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_REMOVE_DIRTY_KEY]))) && count($this->get{$attribute->getMethodName()}()) < {$attribute->_cardinalityLower}) {ldelim}
        $this->validateErrors['{$attribute->_name}'] = $rb->getString('{$attribute->_cardinalityErr}', $params);
      {rdelim}
{/if}
{if $attribute->_cardinality && $attribute->_cardinalityUpper != $smarty.const.SRA_MAX_INT_VAL}
      // validate upper bound of cardinality
      if (isset($this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_ADD_DIRTY_KEY]) && count($this->_dirty['{$attribute->_name}'][SRA_ATTRIBUTE_ADD_DIRTY_KEY]) && count($this->get{$attribute->getMethodName()}()) > {$attribute->_cardinalityUpper}) {ldelim}
        $this->validateErrors['{$attribute->_name}'] = $rb->getString('{$attribute->_cardinalityErr}', $params);
      {rdelim}
{/if}
		{rdelim}
{/if}
{/foreach}

{if $entity->_validateGenerators}
{foreach from=$entity->_validateGenerators item=validator}
{if $validator->_requireAll}{assign var="op" value="||"}{else}{assign var="op" value="&&"}{/if}
		if (({if $validator->_mandatory}!$_id || {/if}in_array('{$validator->_name}', $_id)) && (({assign var="started" value="0"}{foreach from=$validator->_validationSet item=validation}{if $started} {$op} {/if}{if $validation.if}({/if}{if $validation.if && $validation.not}!{/if}{if $validation.if}$this->parseString('{ldelim}${$validation.if}{rdelim}') && ({/if}{assign var="astarted" value="0"}{foreach from=$validation.attrs item=attr}{if $astarted} {$validation.join} {/if}{if $validator->_evalPhpFalse}!{/if}$this->getAttribute('{$attr}'){if !$validator->_evalPhpFalse} === NULL{/if}{assign var="astarted" value="1"}{/foreach}{if $validation.if})){/if}{assign var="started" value="1"}{/foreach}){if $validator->_equal || $validator->_notEqual} || ({assign var="started" value="0"}{foreach from=$validator->_validationSet item=validation}{if !$validation.if}{if $firstAttr}{if $started} || {/if}$this->parseString('{ldelim}${$validation.attr}{rdelim}') {if $validator->_notEqual}=={else}!={/if} $this->parseString('{ldelim}${$firstAttr}{rdelim}'){assign var="started" value="1"}{else}{assign var="firstAttr" value=$validation.attr}{/if}{/if}{/foreach}{assign var="firstAttr" value="0"}){/if})) {ldelim}
			{assign var="attrN" value="1"}
			$params = array('entity' => $rb->getString('{$entity->getResourceName()}'){foreach from=$validator->_validationSet item=validation}, 'attr{$attrN}' => $this->getEntityLabel('{$validation.attr}'){assign var="attrN" value=$attrN+1}{/foreach});
			$this->validateErrors['{$validator->_name}'] = $rb->getString('{$validator->_resource}', $params);
		{rdelim}
{/foreach}
{/if}
    {include file="entity-aspect-after.tpl"}
{if $entity->_parentEntity}
		parent::validate($_id, FALSE);
{/if}
		return count($this->validateErrors) == 0;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} validateDelete
	/**
	 * this validation method is invoked by 'dao.delete' for this entity. if 
   * validation errors are triggered resulting in this method returning FALSE, 
   * the 'dao.delete' invocation will fail with an error being logged. 
   * out-of-the-box this method does not implement any validation logic. if 
   * deletion validation logic is desired, it should be implemented using 
   * "after" aspects for this entity and method. this method also invokes 
   * "validateDelete" on any sub-entities with "on-delete-cascade" constraints
	 * @param boolean $reset whether or not to reset the instance 'validateErrors'
   * attribute
   * @param boolean $mergeErrors whether or not to merge any validate errors 
   * into this objects validateErrors array
	 * @return TRUE for successful validation, FALSE otherwise
	 * @access public
	 */
	function validateDelete($reset=TRUE, $mergeErrors=TRUE) {ldelim}
    {$Template->assign('aopMethodName', "validateDelete")}
    {include file="entity-aspect-before.tpl"}
		if ($reset) {ldelim} $this->validateErrors = array(); {rdelim}
		$rb =& {$className}::getEntityResources();
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->isEntity() && $attribute->_onDeleteCascade}
    if (!$attribute || in_array('{$attribute->_name}', $attribute)) {ldelim}
      if ($attr =& $this->get{$attribute->getMethodName()}()) {ldelim}
{if $attribute->_cardinality}
        $keys = array_keys($attr);
        foreach ($keys as $key) {ldelim}
{/if}
        if (!$attr{if $attribute->_cardinality}[$key]{/if}->validateDelete($reset, $mergeErrors)) {ldelim}
          if ($mergeErrors && $attr{if $attribute->_cardinality}[$key]{/if}->validateErrors) {ldelim}
            $ekeys = array_keys($attr{if $attribute->_cardinality}[$key]{/if}->validateErrors);
            foreach($ekeys as $ekey) {ldelim}
              $this->validateErrors[$ekey] = isset($this->validateErrors[$ekey]) && $this->validateErrors[$ekey] ? $this->validateErrors[$ekey] : $attr{if $attribute->_cardinality}[$key]{/if}->validateErrors[$ekey];
            {rdelim}
          {rdelim}
          else {ldelim}
            $this->validateErrors['{$attribute->_name}'] = $rb->getString('error.subEntity.validateDelete', array('name' => '{$entity->_name}', 'attr' => '{$attribute->_name}'));
          {rdelim}
        {rdelim}
{if $attribute->_cardinality}
        {rdelim}
{/if}
      {rdelim}
    {rdelim}
{/if}
{/foreach}
    {include file="entity-aspect-after.tpl"}
{if $entity->_parentEntity}
		parent::validateDelete(FALSE);
{/if}
		return count($this->validateErrors) == 0;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
  
	// {ldelim}{ldelim}{ldelim} validateSubEntities
	/**
	 * Used to validate any sub-entities contained within this object. ONLY 
   * sub-entities that have been previously loaded (either through a 'get', 
   * 'set' or 'add' invocation) will be validated. if $mergeErrors is TRUE, any 
   * error messages set by the sub-entities will be merged into this objects' 
   * validateErrors messages. 'validateSubEntities' will also be invoked on the 
   * sub-entities unless $recursive is FALSE
   * @param boolean $mergeErrors whether or not to merge any validate errors 
   * into this objects validateErrors array. the keys for the merging will be
   * formatted as follows: [attribute name].[[index (where applicable].][sub attribute]
   * where each error message will be prefixed by the attribute label
   * when FALSE, the 'validateErrors' value will be specific to the entire 
   * attribute using the key [attribute name] and the error message resource key 
   * 'error.subEntity.validate' with the parameters 'name' => 'entity name', 'attr' => 'attribute name'
   * @param string $attribute an optional parameter identifying a specific 
   * sub-entity to validate. all other attributes will be ignored. this param
   * may also be an array representing multiple entities to validate
   * @param boolean $recursive whether or not to invoke 'validateSubEntities' on 
   * the sub-entities
	 * @return TRUE for successful validation, FALSE otherwise
	 * @access public
	 */
	function validateSubEntities($mergeErrors=TRUE, $attribute=FALSE, $recursive=TRUE) {ldelim}
    // detect circular validations and abort when they occur
    static $_validatingSubEntities = array();
    if ($this->_validatingSubEntities || $_validatingSubEntities[$this->getPrimaryKey()]) {ldelim} return TRUE; {rdelim}
    $this->_validatingSubEntities = TRUE;
    $_validatingSubEntities[$this->getPrimaryKey()] = TRUE;
    
    $err = FALSE;
    $attribute = $attribute && !is_array($attribute) ? array($attribute) : $attribute;
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->isEntity()}
    if (!$attribute || in_array('{$attribute->_name}', $attribute)) {ldelim}
      if ($this->_{$attribute->_name}) {ldelim}
{if $attribute->_cardinality}
        $keys = array_keys($this->_{$attribute->_name});
        foreach ($keys as $key) {ldelim}
{/if}
        $this->_{$attribute->_name}{if $attribute->_cardinality}[$key]{/if}->validate();
        if ($recursive) {ldelim} $this->_{$attribute->_name}{if $attribute->_cardinality}[$key]{/if}->validateSubEntities($mergeErrors, $attribute); {rdelim}
        
        if ($this->_{$attribute->_name}{if $attribute->_cardinality}[$key]{/if}->validateErrors) {ldelim}
          if ($mergeErrors) {ldelim}
            $ekeys = array_keys($this->_{$attribute->_name}{if $attribute->_cardinality}[$key]{/if}->validateErrors);
            foreach($ekeys as $ekey) {ldelim}
              $this->validateErrors['{$attribute->_name}.' . {if $attribute->_cardinality}$key . '.' . {/if}$ekey] = $this->getEntityLabel('{$attribute->_name}') . ': ' . $this->_{$attribute->_name}{if $attribute->_cardinality}[$key]{/if}->validateErrors[$ekey];
            {rdelim}
          {rdelim}
          else {ldelim}
            $this->validateErrors['{$attribute->_name}'] = $rb->getString('error.subEntity.validate', array('name' => '{$entity->_name}', 'attr' => '{$attribute->_name}'));
          {rdelim}
        {rdelim}
{if $attribute->_cardinality}
        {rdelim}
{/if}
      {rdelim}
    {rdelim}
{/if}
{/foreach}
{if $entity->_parentEntity}
    if (!$attribute) {ldelim} parent::validateSubEntities($mergeErrors); {rdelim}
{/if}
    $this->_validatingSubEntities = FALSE;
    $_validatingSubEntities[$this->getPrimaryKey()] = FALSE;
    
		return count($this->validateErrors) == 0;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// {ldelim}{ldelim}{ldelim} toString
	/**
	 * Returns a string representation of this object
   * @access public
	 * @return String
	 */
	function toString() {ldelim}
		return SRA_Util::objectToString($this);
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// private operations
	/**
	 * returns TRUE if the current user id (from SRA_Authenticator::getUserId()) 
   * matches the attribute $attr. $attr will be passed to the "getAttribute" 
   * method and the return value of that method compared with the current user 
   * id. if the return value is an array, this method will return true if it 
   * exists in that array. to bypass matching, you may set the global variable
   * 'ignoreMatchErrors' to TRUE
   * @param string $attrId the attribute to match
   * @param string $method the name of the method this  was invoked from (used 
   * for logging purposes only)
   * @access public
	 * @return boolean
	 */
  function _matchUserId($attrId, $method) {ldelim}
    global $ignoreMatchErrors;
    
    if ($ignoreMatchErrors) {ldelim}
      return TRUE;
    {rdelim}
    
    {$Template->assign('aopMethodName', "_matchUserId")}
    {include file="entity-aspect-before.tpl"}
    $userId = class_exists('SRA_Authenticator') ? SRA_Authenticator::getUserId() : NULL;
    $attr = $this->getAttribute($attrId);
    if (!is_array($attr)) {ldelim}
      $attr = array($attr);
    {rdelim}
    $fullAttr = '';
    $keys = array_keys($attr);
    foreach ($keys as $key) {ldelim}
      $fullAttr .= $attr[$key] . ' ';
      //match found
      if ($userId == $attr[$key]) {ldelim}
        {include file="entity-aspect-after.tpl"}
        return TRUE;
      {rdelim}
    {rdelim}
    // no match found
    $msg = "{$className}::_matchUserId: Security Violation for user '${ldelim}userId{rdelim}' and method '${ldelim}method{rdelim}': Attribute: '${ldelim}attrId{rdelim}' did not match in '${ldelim}fullAttr{rdelim}'";
    SRA_Error::logError($msg, __FILE__, __LINE__);
    {include file="entity-aspect-after.tpl"}
    return FALSE;
  {rdelim}
	
	
	// public static methods
	
	// {ldelim}{ldelim}{ldelim} getEntityResources
	/**
	 * Static method that returns a reference to the SRA_ResourceBundle used by this 
	 * entity
	 *
	 * @access	public
	 * @return	SRA_ResourceBundle
	 */
	function &getEntityResources( ) {ldelim}
		static $resources = FALSE;
    
    {$Template->assign('aopMethodName', "getEntityResources")}
    {include file="entity-aspect-before.tpl"}
{if $entity->_resources}
		
		if (!$resources) {ldelim}
			$resources =& SRA_Controller::getAppResources();
{foreach from=$entity->_resources item=res}
			$resources =& SRA_ResourceBundle::merge($resources, SRA_ResourceBundle::getBundle('{$res}'));
{/foreach}
		{rdelim}
		{include file="entity-aspect-after.tpl"}
		return $resources;
{else}
    {include file="entity-aspect-after.tpl"}
		return SRA_Controller::getAppResources();
{/if}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} getEntityResourcesString
	/**
	 * Static method that returns the string corresponding with $key from this 
   * entity's resources
   * @param string $key the id of the resource string to return
   * @param array $params associative array of key/value substitutions to use. 
   * these values can be imbedded into a resource string
	 * @access public
	 * @return string
	 */
	function getEntityResourcesString($key, $params=NULL) {ldelim}
    return SRA_ResourceBundle::isValid($resources =& {$className}::getEntityResources()) ? $resources->getString($key, $params) : $key;
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// {ldelim}{ldelim}{ldelim} getEntityViews
	/**
	 * static method that returns all of the views associated with this entity
	 * 
   * @access public
	 * @return void on success or SRA_Error object otherwises
	 */
	function getEntityViews() {ldelim}
    {$Template->assign('aopMethodName', "getEntityViews")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
		return array({foreach from=$entity->_views item=view}'{$view->_id}', {/foreach});
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// {ldelim}{ldelim}{ldelim} getSysErrorString
	/**
	 * Returns the localized display string that can be used when an unexpected 
	 * error occurs related to this entity. This method is static but can also be 
	 * called from an instance of this class
	 * 
	 * @return string to display for system errors
	 * @access public
	 */
	function getSysErrorString() {ldelim}
    {$Template->assign('aopMethodName', "getSysErrorString")}
    {include file="entity-aspect-before.tpl"}
		$rb =& {$className}::getEntityResources();
    {include file="entity-aspect-after.tpl"}
		return $rb->getString('{$entity->_sysErrResource}');
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
{if !$entity->_skipPersistence}
	// {ldelim}{ldelim}{ldelim} getDao
	/**
	 * Returns the DAO to use for this class
	 * 
   * @param boolean $fresh whether or not a fresh, new instance of the DAO should 
   * be returned. by default, a cached version will be returned if available in 
   * order to take advantage of query caching
	 * @return DAO for this class
	 * @access public
	 */
	function &getDao($fresh = FALSE) {ldelim}
    {$Template->assign('aopMethodName', "getDao")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
		return SRA_DaoFactory::getDao('{$entity->_name}', $fresh);
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} reload
	/**
	 * Reloads the attributes from the database for this {$className} object
	 * 
	 * @return void
	 * @access public
	 */
	function reload() {ldelim}
    {$Template->assign('aopMethodName', "reload")}
    {include file="entity-aspect-before.tpl"}
    $ret = NULL;
    if ($this->getPrimaryKey()) {ldelim}
      $dao =& $this->getDao(TRUE);
      if (method_exists($dao, 'reload')) {ldelim} 
        $obj =& $dao->reload($this);
{foreach from=$entity->getAttributes() item=attribute}
{if $attribute->_lazyLoad || $attribute->_lazyLoadExclusive}
        if ($this->hasBeenSet('{$attribute->_name}')) {ldelim}
          unset($this->_setAttrs['{$attribute->_name}']);
          $obj->getAttribute('{$attribute->_name}');
        {rdelim}
{/if}
{/foreach}
        SRA_Util::mergeObject($this, $obj, TRUE);
      {rdelim}
      else {ldelim}
        $msg = "{$className}::reload: Failed - Cannot reload an object that does not exist in the database";
        $ret =& SRA_Error::logError($msg, __FILE__, __LINE__);
      {rdelim}
      {include file="entity-aspect-after.tpl"}
      return $ret;
    {rdelim}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} insert
	/**
	 * this is a shortcut helper method. the same functionality could be invoked 
   * by first retrieving a reference to the class dao, and then invoking the 
   * insert method on that dao using a reference to this object
	 * 
   * @param boolean $includeSubEntities whether or not sub-entities should also 
   * be checked and updated (only if they have been loaded)
	 * @return void
	 * @access public
	 */
	function insert($insertSubEntities) {ldelim}
    {$Template->assign('aopMethodName', "insert")}
    {include file="entity-aspect-before.tpl"}
    $dao =& $this->getDao();
    if (method_exists($dao, 'insert')) {ldelim} 
      $ret = $dao->insert($this, $insertSubEntities);
      {include file="entity-aspect-after.tpl"}
      return $ret;
    {rdelim}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} update
	/**
	 * this is a shortcut helper method. the same functionality could be invoked 
   * by first retrieving a reference to the class dao, and then invoking the 
   * update method on that dao using a reference to this object
	 * 
   * @param boolean $includeSubEntities whether or not sub-entities should also 
   * be checked and updated (only if they have been loaded)
	 * @return void
	 * @access public
	 */
	function update($updateSubEntities = FALSE) {ldelim}
    {$Template->assign('aopMethodName', "update")}
    {include file="entity-aspect-before.tpl"}
    $dao =& $this->getDao();
    if (method_exists($dao, 'update')) {ldelim} 
      $ret = $dao->update($this, $updateSubEntities);
      {include file="entity-aspect-after.tpl"}
      return $ret;
    {rdelim}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
  
  
	// {ldelim}{ldelim}{ldelim} delete
	/**
	 * this is a shortcut helper method. the same functionality could be invoked 
   * by first retrieving a reference to the class dao, and then invoking the 
   * delete method on that dao using a reference to this object
	 * 
	 * @return void
	 * @access public
	 */
	function delete() {ldelim}
    {$Template->assign('aopMethodName', "delete")}
    {include file="entity-aspect-before.tpl"}
    $dao =& $this->getDao();
    if (method_exists($dao, 'delete')) {ldelim} 
      $ret = $dao->delete($this);
      $this->recordExists = FALSE;
      $this->_{$primaryKey->_name} = NULL;
      {include file="entity-aspect-after.tpl"}
      return $ret;
    {rdelim}
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
{/if}
  
  
	// {ldelim}{ldelim}{ldelim} getEntityType
	/**
	 * Returns the entity name. this value may be used to reference to reference 
   * the correct DAO to use for this class
	 * 
	 * @return the entity name for this class
	 * @access public
	 */
	function getEntityType() {ldelim}
    {$Template->assign('aopMethodName', "getEntityType")}
    {include file="entity-aspect-before.tpl"}
    {include file="entity-aspect-after.tpl"}
		return '{$entity->_name}';
	{rdelim}
	// {rdelim}{rdelim}{rdelim}
	
	
	// {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}
	
	
	/** NEW INSTANCE **/
	// {ldelim}{ldelim}{ldelim} newInstanceFromForm
	/**
	 * Static method used to create a new instance of this value object from the 
	 * values in a posted web form. this takes into account "is-file" attributes 
	 * and form field naming prefixes
	 * 
	 * @param string $submitType determines the PHP global form variable to 
	 * evaluate. the default value is SRA_ENTITY_VO_POST_FORM, meaning the $_POST 
	 * global variable array will be evaluated. SRA_ENTITY_VO_GET_FORM will result 
	 * in the $_GET global variable being evaluated instead. 
	 * SRA_ENTITY_VO_POST_FORM submit types will automatically include uploaded 
	 * files (from the $_FILES global) in the instantiation if they exist. 
   * alternatively, this value may be an array itself containing the values to 
   * initialize the object from
   * @param string $view an optional identifier of the entity view that the 
   * form was generated from. if specified, ONLY attributes included in that 
   * form will be allowed in the $_POST/$_GET data. use this option for 
   * security purposes to eliminate the possiblity of allowing a user to manually 
   * add attributes to the form which in turn would result in automatic setting 
   * of those values. additionally, this deals with the problem of checkboxes
   * and multi-select input fields which will NOT appear in the $_POST/$_GET 
   * data if they are not selected. in order for view filtering to work, the 
   * corresponding view MUST define either sub-attribute, or params where the 
   * id is the name of the attribute where the latter has higher precedence
	 * @param string $prefix a form field identifying prefix. only fields with 
	 * this prefix will be evaluated.
	 * @param string $postfix a form field identifying postfix. only fields with 
	 * this postfix will be evaluated
	 * @return {$className}
	 * @access public
	 */
	function &newInstanceFromForm($submitType = SRA_ENTITY_VO_POST_FORM, $view = NULL, $prefix = NULL, $postfix = NULL) {ldelim}
    {$Template->assign('aopMethodName', "newInstanceFromForm")}
    {include file="entity-aspect-before.tpl"}
		if ($submitType == SRA_ENTITY_VO_POST_FORM) {ldelim}
			$evalVar =& array_merge($_POST, $_FILES);
		{rdelim}
    else if (is_array($submitType)) {ldelim}
      $evalVar =& $submitType;
    {rdelim}
		else {ldelim}
			$evalVar =& $_GET;
		{rdelim}
		if ($prefix && !is_array($prefix)) {ldelim}
			$prefix = array($prefix);
		{rdelim}
		if ($postfix && !is_array($postfix)) {ldelim}
			$postfix = array($postfix);
		{rdelim}
		$initVals = array();
		$keys = array_keys($evalVar);
		foreach ($keys as $key) {ldelim}
			if (!strlen($evalVar[$key])) {ldelim}
				$evalVar[$key] = NULL;
			{rdelim}
			$var = $key;
			if ($prefix) {ldelim}
				foreach ($prefix as $p) {ldelim}
					if (strpos($var, $p) === 0) {ldelim}
						$var = substr($var, strlen($p));
					{rdelim}
				{rdelim}
			{rdelim}
			if ($postfix) {ldelim}
				foreach ($postfix as $p) {ldelim}
					if (strpos($var, $p) === (strlen($var) - strlen($p) - 1)) {ldelim}
						$var = substr($var, 0, (strlen($var) - strlen($p)));
					{rdelim}
				{rdelim}
			{rdelim}
{foreach from=$entity->getAttributes() item=attribute}
			if ('{$attribute->_name}' == $var{if $attribute->isEntity() || $attribute->_cardinality} || strpos($var, '{$attribute->_name}_') === 0{/if}{if $attribute->_isFile} && (!is_array($evalVar[$key]) || (is_array($evalVar[$key]) && array_key_exists('size', $evalVar[$key]) && $evalVar[$key]['size'] > 0)){/if}) {ldelim}
				$initVals[$var] = $evalVar[$key];
			{rdelim}
{if $attribute->_isFile}
      if ('{$attribute->_name}_remove' == $var && $evalVar[$key] == '1') {ldelim}
        $initVals[$var] = TRUE;
      {rdelim}
{/if}
{if $attribute->getAggregateAttributes()}
    // mapped attributes for {$attribute->_name}
{foreach from=$attribute->getAggregateAttributes() item=attr}
    if (('{$attr->_name}' == $var{if $attribute->_isFile} || ('{$attribute->_name}_remove' == $var && $evalVar[$key] == '1'){/if}){if $attr->isEntity() || $attr->_cardinality} || strpos($var, '{$attr->_name}_') === 0{/if}{if $attr->_isFile} && (!is_array($evalVar[$key]) || (is_array($evalVar[$key]) && array_key_exists('size', $evalVar[$key]) && $evalVar[$key]['size'] > 0)){/if}) {ldelim}
      $initVals[$var] = $evalVar[$key];
    {rdelim}
{if $attr->_isFile}
    if ('{$attr->_name}_remove' == $var && $evalVar[$key] == '1') {ldelim}
      $initVals[$var] = TRUE;
    {rdelim}
{/if}
{/foreach}
{/if}
{/foreach}
		{rdelim}
    $keys = array_keys($initVals);
{foreach from=$entity->_views item=view}
    if ($view && $view == '{$view->_id}') {ldelim}
      $allow = array();
{if $view->_params}
{foreach from=$view->_params->getParams('formInitValsPre') key=attr item=val}
      $allow['{$attr}'] = {$val};
{/foreach}
{/if}
{if $view->getAttributes()}
{foreach from=$view->getAttributes() item=attr}
{if $entity->hasAttribute($attr)}
{assign var=attr value=$entity->getAttributes($attr)}
{if $attr->isEntity() || $attr->_cardinality}
      $found = FALSE;
      foreach($keys as $key) {ldelim}
        if (strpos($key, '{$attr->_name}') === 0) {ldelim}
          $found = TRUE;
          $allow[$key] = $initVals[$key];
        {rdelim}
      {rdelim}
      if (!$found) {ldelim}
        $allow['{$attr->_name}'] = NULL;
      {rdelim}
{else}
      {if $attr->_isFile}if ($submitType != SRA_ENTITY_VO_POST_FORM || !array_key_exists('{$attr->_name}', $evalVar) || array_key_exists('{$attr->_name}', $initVals)) {/if}$allow['{$attr->_name}'] = isset($initVals['{$attr->_name}']) ? $initVals['{$attr->_name}'] : (isset($allow['{$attr->_name}']) ? $allow['{$attr->_name}'] : NULL);
{/if}
{/if}
{/foreach}
{elseif $view->_params}
{foreach from=$view->_params->getParams() key=attr item=val}
{if $entity->hasAttribute($attr)}
{assign var=attr value=$entity->getAttributes($attr)}
{if $attr->isEntity() || $attr->_cardinality}
      $found = FALSE;
      foreach($keys as $key) {ldelim}
        if (strpos($key, '{$attr->_name}') === 0) {ldelim}
          $found = TRUE;
          $allow[$key] = $initVals[$key];
        {rdelim}
      {rdelim}
      if (!$found) {ldelim}
        $allow['{$attr->_name}'] = NULL;
      {rdelim}
{else}
      {if $attr->_isFile}if ($submitType != SRA_ENTITY_VO_POST_FORM || !array_key_exists('{$attr->_name}', $evalVar) || array_key_exists('{$attr->_name}', $initVals)) {/if}$allow['{$attr->_name}'] = array_key_exists('{$attr->_name}', $initVals) ? $initVals['{$attr->_name}'] : (isset($allow['{$attr->_name}']) ? $allow['{$attr->_name}'] : NULL);
{if $attr->_isFile}
      if (array_key_exists('{$attr->_name}_remove', $initVals)) $allow['{$attr->_name}_remove'] = $initVals['{$attr->_name}_remove'];
{/if}
{/if}
{/if}
{/foreach}
{/if}
{if $view->_params}
{foreach from=$view->_params->getParams('formInitVals') key=attr item=val}
      $allow['{$attr}'] = {$val};
{/foreach}
{foreach from=$view->_params->getParams('formInitValsRemove') key=attr item=val}
      if (array_key_exists('{$attr}', $allow){if $val} && $allow['{$attr}'] == {$val}{/if}) {ldelim}
        unset($allow['{$attr}']);
      {rdelim}
{/foreach}
{/if}
      $initVals = $allow;
    {rdelim}
{/foreach}
    
    {include file="entity-aspect-after.tpl"}
		return new {$className}($initVals);
	{rdelim}
	// {rdelim}{rdelim}{rdelim}

  
{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}


// {ldelim}{ldelim}{ldelim} Imports
{foreach from=$entity->getIncludes() item=inc}
require_once('{$inc}');
{/foreach}
// {rdelim}{rdelim}{rdelim}
?>
Return current item: Sierra-php PHP Application Framework