Index: trunk/prototype/app/controller.php
===================================================================
--- trunk/prototype/app/controller.php	(revision 5136)
+++ trunk/prototype/app/controller.php	(revision 5341)
@@ -1,230 +1,634 @@
 <?php
 
-require_once "service.php";
+if( !defined( 'ROOTPATH' ) )
+    define( 'ROOTPATH', dirname(__FILE__).'/..' );
+
+require_once(ROOTPATH.'/app/config.php');
+
+/**
+TODO list:
+
+  * definir de forma centralizada os caminhos e as constantes necessÃ¡rias;
+  * criar um User Agent detect e um OS server detect para customizaÃ§Ãµes espeÃ§Ã­ficas de cada browser / servidor;
+  * criar um registrador para fallback handlers;
+  * criar um dependency manager na configuraÃ§Ã£o dos serviÃ§os, para poder gerenciar os imports corretamente
+  * criar um login e a recuperaÃ§Ã£o da sessÃ£o;
+
+*/
 
 class Controller {
 
-	var $config;
-	var $className;
-	var $parent;
-	var $target;
-	var $cache;
-	var $service;
-	var $includes;
-
-	public static function newInstance( $className, $id = false, $parents = false  )
-	{
-	    return new Controller( $className, $id, $parents );
-	}
-
-	public function __construct( $className, $id = false, $parents = false )
-	{
-	    $this->className = $className;
-
-	    if( is_array( $id ) )
-	    {
-		$parents = $id;
-		$id = null;
-	    }
-
-	    $this->parents = $parents;
-	    $this->target = $id;
-	    $this->includes = array();
-
+	static $cache;
+	static $services = array();
+	static $interceptors = array();
+	static $config = array();
+	static $includes = array();
+	static $tx = array();
+	static $txID = 0;
+	static $wallet;
+
+	public function __destruct()
+	{
+// 	    if( $this->service )
+// 		$this->service->close();
+// 	    else
+	    self::closeAll();
+	}
+
+	public static function closeAll()
+	{
+	    if( self::$services )
+		foreach( self::$services as $serviceName => $service )
+		    if( self::$config[ $serviceName ]['type'] === 'service' )
+		      $service->close();
+	}
+
+	public static function clearAll()
+	    {
+	    return self::$cache->clearAll();
+	    }
+
+	public static function clear( $id )
+	{
+	    return self::$cache->clear( $id );
+	}
+
+	public static function check( $id )
+	{
+	    return self::$cache->get( $id );
+	}
+
+	public static function store( $id, $data, $expires, $compressed )
+	{
+	    return self::$cache->put( $id, $data, $expires, $compressed );
+	}
+
+	public static function put( $URI, $data, $txIds = false )
+	{
+	    try
+	    {
+		$URI = self::serviceName( $URI );
+
+		if( $commit = !$txIds )
+			    $txIds = array();
+
+		if( !isset( self::$tx[ $URI['service'] ] ) )
+		{
+			    self::call( 'begin', $URI );
+			    self::$tx[ $txIds[] = $URI['service'] ] = array();
+	    }
+
+		$method = $data ? isset( $data['id'] ) ?
+			  'update' : 'create' : 'delete';
+
+		$links = self::links( $URI['concept'] );
+
+		$Tx = array( 'order' => self::$txID++ );
+
+		$postpone = array();
+
+		if( $data )
+		{
+		    $URI['id'] = isset( $data['id'] ) ? $data['id'] : false;
+
+		    foreach( $links as $linkName => $linkTarget )
+		    {
+				if( isset( $data[$linkName] ) && is_array( $data[$linkName] ) )
+				{
+					if( self::isConcept( $linkName ) )
+						$data[$linkName] = self::put( array( 'concept' => $linkTarget ), $data[$linkName], &$txIds );
+					else
+						$postpone[$linkTarget] = $data[$linkName];
+				}
+	}
+		}
+		else
+		  $URI['id'] = isset( $data['id'] ) ? $data['id'] : $URI['id'];
+
+		$result = Controller::call( $method, $URI, $data, false, false, true );
+
+		if( !is_bool( $result ) && !is_string( $result ) && isset( $result['id'] ) )
+		      $URI['id'] = $result['id'];
+
+		self::$tx[ $URI['service'] ][] = array_merge( $Tx, array( 'id' => $URI['id'], 'concept' => $URI['concept'], 'method' => $method, 'service' => $URI['service'], 'rollback' => !!!$result ) );
+
+		foreach( $postpone as $linkTarget => $dt )
+		      foreach( $dt as $ii => $value )
+	{
+			  if( !is_array( $value ) )
+			    $value = array( 'id' => $value );
+
+			  $value[ $URI['concept'] ] = $URI['id'];
+
+			  self::put( array( 'concept' => $linkTarget ), $value, &$txIds );
+	}
+
+		if( $commit )
+	{
+		      $result = array();
+
+		      for( $i = count( $txIds ) - 1; $i >= 0; $i-- )
+		      {
+			      $currentTx = self::$tx[ $txIds[$i] ];
+			      unset( self::$tx[ $txIds[$i] ] );
+
+			      if( !self::commit( array( 'service' => $txIds[$i] ), $currentTx ) )
+			      {
+				  self::rollback( array( 'service' => $txIds[$i] ), $currentTx );
+
+				  foreach( $currentTx as $i => $st )
+				      $currentTx[$i][ 'rollback' ] = true;
+	}
+
+			      $result = array_merge( $result, $currentTx );
+		      }
+			  
+			  self::$txID = 0;
+
+		      return( $result );
+		}
+
+	    }
+	    catch( Exception $e )
+	{
+		if( !self::fallback( $e ) )
+		    self::closeAll();
+
+		return( false );
+	    }
+	
+	    return( $URI['id'] );
+	}
+	
+	public static function get()
+	    {
+	    
+	    }
+
+	public static function find( $URI, $params = false, $criteria = false )
+	{
+	    if( isset($URI['id']) && $URI['id'] )
+		return self::read( $URI, $params, $criteria );
+	    
+	    return self::call( 'find', $URI, $params, $criteria );
+	}
+
+	public static function read( $URI, $params = false, $criteria = false )
+	{
+	    if( !isset($URI['id']) || !$URI['id'] )
+		return self::find( $URI, $params, $criteria );
+
+	    return self::call( 'read', $URI, $params, $criteria );
+	}
+
+	public static function deleteAll( $URI, $params = false, $criteria = false )
+	{
+	    if( isset($URI['id']) && $URI['id'] )
+		return self::delete( $URI, $params, $criteria );
+
+	    return self::call( 'deleteAll', $URI, $params, $criteria );
+	}
+
+	public static function delete( $URI, $params = false, $criteria = false )
+	{
+	    if( !isset($URI['id']) || !$URI['id'] )
+		return self::deleteAll( $URI, $params, $criteria );
+
+	    return self::call( 'delete', $URI, $params, $criteria );
+	}
+
+	public static function replace( $URI, $params, $criteria = false )
+	{
+	    if( isset($URI['id']) && $URI['id'] )
+		return self::update( $URI, $params, $criteria );
+
+	    return self::call( 'replace', $URI, $params, $criteria );
+	}
+
+	public static function update( $URI, $params, $criteria = false )
+	{
+	    if( !isset($URI['id']) || !$URI['id'] )
+		return self::replace( $URI, $params, $criteria );
+
+	    return self::call( 'update', $URI, $params, $criteria );
+	}
+
+	public static function create( $URI, $params, $criteria = false )
+	{
+	    return self::call( 'create', $URI, $params, $criteria );
+	}
+
+	public static function begin( $URI, $params = false, $criteria = false )
+	{
+	    return self::call( 'begin', $URI, $params, $criteria );
+	}
+
+	public static function commit( $URI, $criteria = false )
+	    {
+	    return self::call( 'commit', $URI, false, $criteria );
+	}
+
+	public static function rollback( $URI, $criteria = false )
+	{
+	    return self::call( 'rollback', $URI, false, $criteria );
+	}
+
+	public static function format( $URI, $params, $criteria = false )
+	{
+	    return self::call( 'format', $URI, $params, $criteria );
+	}
+
+	public static function parse( $URI, $data, $criteria = false )
+	{
+	    return self::call( 'parse', $URI, $data, $criteria );
+	    }
+
+	public static function URI( $className, $id = false, $service = false )
+	{
+	    return array( 'concept' => $className,
+			  'service' => $service ? $service : false, 
+			  'id' => $id ? $id : '' );
+	}
+
+	public static function links( $concept )
+	{
+	    if( !isset(self::$config[ $concept ]) )
+	      self::$config[ $concept ] = self::loadConfig( $concept );
+
+	    return( isset(self::$config[ $concept ]['links']) ? 
+			  self::$config[ $concept ]['links'] : array() );
+	}
+
+	public static function isConcept( $concept )
+	    { 
+	    if( isset( self::$config[ $concept ] ) && 
+		self::$config[ $concept ] )
+		return( true );
+		else
+		return file_exists( ROOTPATH."/config/$concept.ini" );
+	}
+
+	public static function getConcept( $concept )
+	{
+	    if( isset( self::$config[ $concept ] ) )
+		return( self::$config[ $concept ] );
+
+	    return( self::$config[ $concept ] = self::loadConfig( $concept ) );
+	    }
+
+	public static function loadCache( $cacheType = 'Memory' )
+	{
 	    include_once( "cache/MemoryCache.php" );
-	    $this->cache = new MemoryCache();
-
-	    $this->config = $this->cache->get( "$className.ini" );
-
-	    if( !$this->config )
-	    {
-		$this->config = parse_ini_file( "config/$className.ini", true );
-
-		$this->cache->put( "$className.ini", $this->config[$className] );
-	    }
-
-	    $this->service = $this->load( "service" );
-
-	    if( $this->service )
-		$this->service->connect( $this->config["config"] );
-	}
-
-	public function __destruct()
-	{
-	    if( $this->service )
-		$this->service->close();
-	}
-
-	public function load( $type )
-	{
-	    if( !$this->config[$type] )
+	    return new MemoryCache();
+	}
+
+	public static function loadConfig( $className, $isService = false )
+	{
+	    $fileName = $className.'.'.($isService ? 'srv' : 'ini');
+
+	    $config = self::$cache->get( $fileName );
+
+	    if( !$config )
+	    {
+		$config = parse_ini_file( ROOTPATH."/config/$fileName", true );
+
+		self::$cache->put( $fileName, $config );
+	    }
+
+	    return( $config );
+	}
+
+	public static function import( $path, $ext = ".php" )
+	{ 
+	    if( !isset(self::$includes[$path]) )
+	{
+		require_once( ROOTPATH.'/'.$path.$ext );
+		self::$includes[$path] = false;
+	    }
+
+	    return( self::$includes[$path] );
+	}
+
+	public static function load( $path, $class = false )
+	    { 
+            if( $return = self::import( $path, "" ) )
+		return( $return );
+
+	    if( !$class ){
+		preg_match( '/^\/?.*\/([^\/]+).php$/', $path, $class );
+		$class = $class[1];
+	    }
+
+	    $object =  self::$cache->get( $class );
+
+	    if( !$object )
+	    {
+		$object = new $class();
+		 self::$cache->put( $class, $object );
+	    }
+
+	    self::$includes[$path] = $object;
+
+	    return( $object );
+	}
+
+	public static function wallet( $serviceName )
+	{
+	    if( !isset( self::$wallet ) )
+	    {
+		//// Hack //// TODO: passar o init da sessÃ£o no login do expresso
+		Config::init();
+
+                if(isset($_SESSION['wallet']))
+                    self::$wallet = $_SESSION['wallet'];
+		/////////////
+	    }
+
+	    return isset( self::$wallet[ $serviceName ] )? self::$wallet[ $serviceName ] : false;
+	}
+		
+	public static function connect( $service, $config )
+	    {
+	    $result = $service->open( $config );
+
+	    if( is_string( $result ) )
+		throw new Exception( $result );
+
+	    return( true );
+	}
+
+	public static function configure( $config, $newConfig )
+	{
+	    foreach( $newConfig as $key => $value )
+		$config[$key] = $value;
+
+	    return( $config );
+	    }
+
+	public static function dispatch( $dispatcher, $data, $optionsMap = false )
+	{
+// 	    if( $mappedTo )
+// 		$data = array( $mappedTo => $data );
+// 
+// 	    foreach( $data as $method => $params )
+// 	    {
+// // 		foreach( $data[ $method ] as $name => $value )
+// 	    }
+// 
+// 	    self::import( "$dispatcher.php" );
+	}
+
+	public static function service( $serviceName, $concept = false )
+	{
+	    if( isset( self::$services[ $serviceName ] ) )
+		return self::$services[ $serviceName ];
+
+	    if( !isset(self::$config[ $serviceName ]) )
+		 self::$config[ $serviceName ] = self::loadConfig( $serviceName, true );
+
+	    if( !isset(self::$config[ $serviceName ]) )
 		return( false );
 
-	    return $this->import( $this->config[$type]["path"],
-							  $this->config[$type]["class"] );
-	}
-
-	public function import( $path, $class )
-	{
-	    if( !$class ){
-		preg_match( "/^\/?.*\/([^\/]+).php$/", $path, $class );
-		$class = $class[1];
-	    }
+	    if( !isset(self::$config[ $serviceName ]['type']) )
+		self::$config[ $serviceName ]['type'] = 'service';
+
+	    self::import( 'app/'.self::$config[ $serviceName ]['type'] );   //TODO: Item 4
+
+	    $service = self::load( self::$config[ $serviceName ]['path'],
+				   self::$config[ $serviceName ]['class'] );
+
+	      $srvConfig = array();
+
+	    if( isset(self::$config[ $serviceName ][ 'config' ]) )
+		$srvConfig = self::configure( $srvConfig, self::$config[ $serviceName ][ 'config' ] );
+	    if( $wallet = self::wallet( $serviceName ) )
+		$srvConfig = self::configure( $srvConfig, $wallet );
+	    if( $concept && isset(self::$config[ $concept ]['service.config']) )
+		$srvConfig = self::configure( $srvConfig, self::$config[ $concept ]['service.config'] );
+
+	    if( empty( $srvConfig ) )
+		$srvConfig = false;
+
+	    if( $service && self::$config[ $serviceName ]['type'] === 'service' )
+		self::connect( $service, $srvConfig );
+
+	    return( self::$services[ $serviceName ] = $service );
+	}
+
+	public static function interceptor( $method, $concept = false, $serviceName = false, $isService = false )
+	{
+	    if( $concept && !isset(self::$config[ $concept ]) )
+	      self::$config[ $concept ] = self::loadConfig( $concept );
+
+	    if( !$concept ) $concept = 'global';
+	    if( !$isService || !$serviceName ) $serviceName = 'global';
+
+	    if( !isset( self::$interceptors[ $concept ] ) )
+		self::$interceptors[ $concept ] = array();
+
+	    if( !isset( self::$interceptors[ $concept ][ $serviceName ] ) )
+		self::$interceptors[ $concept ][ $serviceName ] = array();
+
+	    if( !isset( self::$interceptors[ $concept ][ $serviceName ][ $method ] ) )
+	    {
+		$events = array( 'before', 'after' );
+		$interceptors = array();
+
+		$prefix = ( $isService )? "$serviceName." : "";
+
+		foreach( $events as $i => $event )
+		{
+		    $interceptors[$event] = array();
+
+		    if( !isset(self::$config[$concept]["$prefix$event.$method"]) )
+		      continue;
+
+		    foreach( self::$config[$concept]["$prefix$event.$method"] as $intercept => $interceptor )
+			    $interceptors[$event][$intercept] = self::load( $interceptor );
+		}
+
+		self::$interceptors[ $concept ][ $serviceName ][ $method ] = $interceptors;
+	    }
+
+	    return( self::$interceptors[ $concept ][ $serviceName ][ $method ] );
+	}
+
+	public static function interceptorCommit( $eventType, $commitList, $isService = false )
+	{
+	    $result = array( $eventType => array() );
+        
+        if( is_array( $commitList ) )
+	        foreach( $commitList as $i => $tx )
+	        {
+		    $interceptors = self::interceptor( 'commit', $tx['concept'], $tx['service'], $isService );
+      
+		    $result[$eventType] = array_merge( $result[$eventType], $interceptors[$eventType] );
+	        }
+
+	    return( $result );
+	}
+
+	public static function fire( $eventType, $method, &$params, $original, $isService = false )
+	{
+	    if( $method === 'commit' )
+		$interceptors = self::interceptorCommit( $eventType, $params['criteria'], $isService );
+
+	    else
+		$interceptors = self::interceptor( $method,
+						   isset($original['URI']['concept']) ? $original['URI']['concept'] : false,
+						   isset($params['URI']['service']) ? $params['URI']['service'] : false, $isService );
+
+	    if( $interceptors && isset($interceptors[ $eventType ]) )
+		foreach( $interceptors[ $eventType ] as $intercept => $interceptor )
+		{
+		    $return = $interceptor->$intercept( $params['URI'], $params['properties'], $params['criteria'], $original/*, $params['service']*/ );
+
+		    if( $return === false )
+		return( false );
+
+		    if( isset($return) )
+			$params['properties'] = $return;
+		}
+
+	      return( $params );
+	}
+
+	/*
+	  * ex: array
+	  *		(
+	  *			[0] array( 'OR', array( array( '=', 'campo', 'valor' ), 
+							  array( 'OR', array( array( '=', 'campo', 'valor' ) ) ) )
+	  *			[1] array( '=', 'campo' , 'valor' )
+	  *			[2] array( 'OR' , array( array( '=' , campo', 'valor' ) ) )
+	  *			[3] array( 'IN', 'campo', array( '1' , '2' , '3' ) )
+	  *		)
+	  * OR
+	  *	    array( '=' , 'campo' , 'valor' )
+	*/
 	
-	    if( !$this->includes[$path] )
-	    {
-		include_once( $path );
-		$this->includes[ $path ] = true;
-	    }
-
-	    $object = $this->cache->get( $class );
-	    
-	    if( $object )
-		return( $object );
-
-	    $object = new $class();
-	    $this->cache->put( $class, $object );
-
-	    return( $object );
-	}
-
-	public function clearAll()
-	{
-	    return $this->cache->clearAll();
-	}
-
-	public function clear( $id )
-	{
-	    return $this->cache->clear( $id );
-	}
-
-	public function get( $id )
-	{
-	    return $this->cache->get( $id );
-	}
-
-	public function put( $id, $data, $expires, $compressed )
-	{
-	    return $this->cache->put( $id, $data, $expires, $compressed );
-	}
-
-	public function fireEvent( $event, $method, $params )
-	{
-	    if( !$this->config["$event.$method"] )
-		return( $params );
-
-	    $original = $params;
-
-	    foreach( $this->config["$event.$method"] as $intercept => $interceptor )
-	    {
-		  if( is_string( $interceptor ) )
-		      $this->config["$event.$method"][$intercept] = $interceptor = $this->import( $interceptor );
-
-		  $return = $interceptor->$intercept( $original, $params );
-
-		  if( $return === false )
-		      return( false );
-
-		  if( $return )
-		      $params = $return;
-	    }
-
-	    return( $params );
-	}
-
-	public function find( $params, $criteria = false )
-	{
-
-	    if( ($params = $this->fireEvent( "before", "find", $params )) === false )
-		 return( false );
-
-	    if( $this->service )
+	public static function serviceName( $URI, $original = false )
+	{
+	     $concept = "";
+
+	    if( $original && isset($original['concept']) && $original['concept'] )
+		$concept = $original['concept'];
+	    elseif( isset($URI['concept']) && $URI['concept'] )
+		$concept = $URI['concept'];
+
+	    if( ( !isset($URI['service']) || !$URI['service'] ) && $concept )
+	    {
+		if( !isset(self::$config[ $concept ]) )
+		    self::$config[ $concept ] = self::loadConfig( $concept );
+
+		$URI['service'] = self::$config[ $concept ][ 'service' ];
+	    }
+
+	    if( !isset($URI['service']) )
+		throw new Exception( "CONFIGURATION ERROR: service name from concept '$concept' not found" );
+
+	    return( $URI );
+	}
+
+	public static function call( $method, $URI, $properties = false, $options = false, $service = false, $noTX = false )
+	{
+	    try
+	    {
+		if( !isset($URI['concept']) ) $URI['concept'] = false;
+
+		$original = $params = array( 'properties' => $properties, 
+				             'criteria' => $options, 
+					     'URI' => $URI,
+					     'service' => $service );
+
+		if( isset($params['URI']['concept'])  && !self::fire( 'before', $method, $params, $original ) )
+		    return( empty($params['properties']) ? false : $params['properties'] );
+
+		if( $params && !$params['service'] )
+		{
+		    $params['URI'] = self::serviceName( $params['URI'], $original['URI'] );
+
+		    $params['service'] = self::service( $params['URI']['service'], $params['URI']['concept'] );
+		}
+
+		if( isset($params['URI']['service']) )
+		{
+		    if( $commit = (!isset(self::$tx[ $params['URI']['service'] ]) && ( $method === 'create' ||
+										       $method === 'update' ||
+										       $method === 'delete' )) )
+		    {
+			self::call( 'begin', $params['URI'] );
+			self::$tx[ $params['URI']['service'] ] = true;
+		    }
+
+		    if( !self::fire( 'before', $method, $params, $original, true ) )
+			return( empty($params['properties']) ? false : $params['properties'] );
+		}
+
+		if( $params['service'] )
+		    switch( $method )
 	    { 
-		if( $this->target )
-		  $result = $this->service->retrieve( $this->className, $this->target, $this->parents, $params, $criteria );
-		else
-		  $result = $this->service->find( $this->className, $this->parents, $params, $criteria );
-
-		if( $result )
-		    $params = $result;
-	    }
-
-	    if( ($result = $this->fireEvent( "after", "find", $params )) === false )
-		 return( false );
-
-	    $result = json_encode( $result );
-
-	    return( $result );
-	}
-
-	public function update( $params, $criteria = false )
-	{
-
-	    if( !($params = $this->fireEvent( "before", "update", $params )) )
+			case 'find': $return = $params['service']->find( $params['URI'], $params['properties'], $params['criteria'] ); break;
+
+			case 'read': $return = $params['service']->read( $params['URI'], $params['properties']/*, $criteria*/ ); break;
+
+			case 'create': $return = $params['service']->create( $params['URI'], $params['properties']/*, $criteria*/ ); break;
+
+			case 'delete': $return = $params['service']->delete( $params['URI'], $params['properties']/*, $criteria*/ ); break;
+
+			case 'deleteAll': $return = $params['service']->deleteAll( $params['URI'], $params['properties'], $params['criteria'] ); break;
+
+			case 'update': $return = $params['service']->update( $params['URI'], $params['properties']/*, $criteria*/ ); break;
+
+			case 'replace': $return = $params['service']->replace( $params['URI'], $params['properties'], $params['criteria'] ); break;
+
+			case 'begin': $return = $params['service']->begin( $params['URI'] ); break;
+
+			case 'commit': $return = $params['service']->commit( $params['URI'], $params['criteria'] ); break;
+
+			case 'rollback': $return = $params['service']->rollback( $params['URI'], $params['criteria'] ); break;
+
+			case 'parse': $return = $params['service']->parse( $params['properties'], $params['criteria'] ); break;
+
+			case 'format': $return = $params['service']->format( $params['properties'], $params['criteria'] ); break;
+	    }
+
+		if( isset($return) && $return !== false )
+		    $params['properties'] = $return;
+
+		if( isset($params['URI']['service']) )
+		{
+		    if( !self::fire( 'after', $method, $params, $original, true ) )
+			return( empty($params['properties']) ? false : $params['properties'] );
+
+		    if( $commit )
+		    {
+			if( !self::call( 'commit', $params['URI'], false, self::$tx[ $params['URI']['service'] ] ) )
+			    self::call( 'rollback', $params['URI'] , false, self::$tx[ $params['URI']['service'] ] );
+
+			unset( self::$tx[ $params['URI']['service'] ] );
+		    }
+		}
+
+		if( isset($URI['concept']) && !self::fire( 'after', $method, $params, $original ) )
+		    return( empty($params['properties']) ? false : $params['properties'] );
+	    }
+	    catch( Exception $e )
+	    {
+		if( !self::fallback( $e ) )
+		    self::closeAll();
+
 		return( false );
-
-	    if( $this->service )
-	    { 
-		if( is_string( $idOrfilter ) )
-		    $result = $this->service->update( $this->className, $this->target, $this->parents, $params, $criteria );
-		else
-		    $result = $this->service->replace( $this->className, $this->parents, $params, $criteria );
-
-		if( $result )
-		    $params = $result;
-	    }
-
-	    if( !($result = $this->fireEvent( "after", "update", $params )) )
-		return( false );
-
-	    $result = json_encode( $result );
-
-	    return( $result );
-	}
-
-	public function delete( $params, $criteria = false )
-	{
-	    if( ($params = $this->fireEvent( "before", "delete", $params )) === false )
-		return( false );
-		
-	    if( $this->service )
-	    {
-		if( is_string( $idOrfilter ) )
-		    $result = $this->service->delete( $this->className, $this->target, $this->parents, $params, $criteria );
-		else
-		    $result = $this->service->deleteAll( $this->className, $this->parents, $params, $criteria );
-
-		if( $result )
-		    $params = $result;
-	    }
-
-	    if( ($result = $this->fireEvent( "after", "delete", $params )) === false )
-		return( false );
-
-	    $result = json_encode( $result );
-
-	    return( $result );
-	}
-
-	public function create( $params )
-	{
-	    if( ($params = $this->fireEvent( "before", "create", $params )) === false )
-		return( false );
-
-	    if( $this->service )
-	    { 
-		$result = $this->service->create( $this->className, $this->parents, $params );
-
-		if( $result )
-		    $params = $result;
-	    }
-
-	    if( ($result = $this->fireEvent( "after", "create", $params )) === false )
-		return( false );
-
-	    $result = json_encode( $result );
-
-	    return( $result );
+	    }
+
+	    return( empty($params['properties']) ? false : $params['properties'] );
+	}
+
+	public static function fallback( $exception )
+	{
+	    error_log( $exception->getMessage() );
+	    return( true );
 	}
 }
+
+Controller::$cache = Controller::loadCache();
 ?>
