Index: /trunk/expressoCalendar/setup/default_records.inc.php
===================================================================
--- /trunk/expressoCalendar/setup/default_records.inc.php	(revision 5514)
+++ /trunk/expressoCalendar/setup/default_records.inc.php	(revision 5715)
@@ -24,5 +24,8 @@
 		//calendar_repeat
 		$oProc->query("ALTER TABLE calendar_repeat ADD CONSTRAINT fk_calendar_repeat_calendar_object FOREIGN KEY (object_id) REFERENCES calendar_object (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE;");
-	
+
+		//calendar_repeat_occurrence
+		$oProc->query("ALTER TABLE calendar_repeat_occurrence ADD CONSTRAINT fk_calendar_repeat_to_calendar_repeat_occurrence FOREIGN KEY (repeat_id) REFERENCES calendar_repeat (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE;");	
+
 		//calendar_signature
 		$oProc->query("ALTER TABLE calendar_signature ADD CONSTRAINT fk_calendar_signature_calendar_espec FOREIGN KEY (calendar_id) REFERENCES calendar (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE;");
Index: /trunk/expressoCalendar/setup/tables_current.inc.php
===================================================================
--- /trunk/expressoCalendar/setup/tables_current.inc.php	(revision 5592)
+++ /trunk/expressoCalendar/setup/tables_current.inc.php	(revision 5715)
@@ -215,5 +215,6 @@
                 'id' => array( 'type' => 'auto', 'nullable' => False),
                 'frequency' => array(  'type' => 'varchar','precision' => '20', 'nullable' => False),
-                'until' => array(  'type' => 'int', 'precision' => '8', 'nullable' => False),
+                'until' => array(  'type' => 'int', 'precision' => '8', 'nullable' => True),
+		'dtstart' => array(  'type' => 'bigint','precision' => '16', 'nullable' => True),
                 'count' => array(  'type' => 'int', 'precision' => '8', 'nullable' => True),
                 'object_id' => array(  'type' => 'int', 'precision' => '8', 'nullable' => False),
@@ -236,4 +237,30 @@
 		),
 
+	    'calendar_repeat_ranges' => array(
+            'fd' => array(
+                'id' => array( 'type' => 'auto', 'nullable' => False),
+                'range_start' => array(  'type' => 'bigint','precision' => '16', 'nullable' => False),
+                'range_end' => array(  'type' => 'bigint', 'precision' => '16', 'nullable' => False),
+                'user_info_id' => array(  'type' => 'bigint', 'precision' => '16', 'nullable' => False)
+            ),
+            'pk' => array('id'),
+            'fk' => array(),
+            'ix' => array(),
+            'uc' => array()
+		),
+
+	    'calendar_repeat_occurrence' => array(
+            'fd' => array(
+                'id' => array( 'type' => 'auto', 'nullable' => False),
+                'occurrence' => array(  'type' => 'bigint','precision' => '16', 'nullable' => False),
+                'repeat_id' => array(  'type' => 'int', 'precision' => '8', 'nullable' => False)
+            ),
+
+            'pk' => array('id'),
+            'fk' => array('repeat_id'),
+            'ix' => array(),
+            'uc' => array()
+		),
+
 		'calendar_signature' => array(
             'fd' => array(
Index: /trunk/expressoCalendar/setup/tables_update.inc.php
===================================================================
--- /trunk/expressoCalendar/setup/tables_update.inc.php	(revision 5651)
+++ /trunk/expressoCalendar/setup/tables_update.inc.php	(revision 5715)
@@ -33,3 +33,45 @@
         return $GLOBALS['setup_info']['expressoCalendar']['currentver'];
 	}
+
+	$test[] = '1.001';
+	function expressoCalendar_upgrade1_001() {
+
+		$oProc = $GLOBALS['phpgw_setup']->oProc;
+
+		$oProc->query("ALTER TABLE calendar_repeat ADD COLUMN dtstart bigint");
+		$oProc->query('ALTER TABLE calendar_repeat ALTER COLUMN until DROP NOT NULL');
+
+		$oProc->CreateTable('calendar_repeat_occurrence', array(
+				'fd' => array(
+				    'id' => array( 'type' => 'auto', 'nullable' => False),
+				    'occurrence' => array(  'type' => 'bigint','precision' => '16', 'nullable' => False),
+				    'repeat_id' => array(  'type' => 'int', 'precision' => '8', 'nullable' => False)
+				),
+
+				'pk' => array('id'),
+				'fk' => array('repeat_id'),
+				'ix' => array(),
+				'uc' => array()
+				)
+		);
+
+		$oProc->CreateTable('calendar_repeat_ranges', array(
+				'fd' => array(
+				    'id' => array( 'type' => 'auto', 'nullable' => False),
+				    'range_start' => array(  'type' => 'bigint','precision' => '16', 'nullable' => False),
+				    'range_end' => array(  'type' => 'bigint', 'precision' => '16', 'nullable' => False),
+				    'user_info_id' => array(  'type' => 'bigint', 'precision' => '16', 'nullable' => False)
+				),
+				'pk' => array('id'),
+				'fk' => array(),
+				'ix' => array(),
+				'uc' => array()
+				    )
+		);
+
+		$oProc->query("ALTER TABLE calendar_repeat_occurrence ADD CONSTRAINT fk_calendar_repeat_to_calendar_repeat_occurrence FOREIGN KEY (repeat_id) REFERENCES calendar_repeat (id) MATCH SIMPLE ON UPDATE CASCADE ON DELETE CASCADE;");	
+
+		$GLOBALS['setup_info']['expressoCalendar']['currentver'] = '1.002';
+        return $GLOBALS['setup_info']['expressoCalendar']['currentver'];
+	}
 ?>
Index: /trunk/expressoCalendar/setup/setup.inc.php
===================================================================
--- /trunk/expressoCalendar/setup/setup.inc.php	(revision 5617)
+++ /trunk/expressoCalendar/setup/setup.inc.php	(revision 5715)
@@ -13,24 +13,26 @@
 	$setup_info['expressoCalendar']['title']     	= 'Expresso Calendar';
 	/* Ao incrementar versão, não esquecer de declarar função do tables_update.inc.php*/
-	$setup_info['expressoCalendar']['version']   	= '1.001';
+	$setup_info['expressoCalendar']['version']   	= '1.002';
 	$setup_info['expressoCalendar']['app_order']	= 10;
         
-		$setup_info['expressoCalendar']['tables'][]		=  'attachment';
-		$setup_info['expressoCalendar']['tables'][]		=  'calendar_attach';
-		$setup_info['expressoCalendar']['tables'][]		=  'calendar_class'; 
-		$setup_info['expressoCalendar']['tables'][]		=  'calendar';
-		$setup_info['expressoCalendar']['tables'][]		=  'calendar_alarm';
-		$setup_info['expressoCalendar']['tables'][]		=  'calendar_ex_participant'; 
-		$setup_info['expressoCalendar']['tables'][]		=  'calendar_object'; 
-		$setup_info['expressoCalendar']['tables'][]		=  'calendar_object_type';
-		$setup_info['expressoCalendar']['tables'][]		=  'calendar_participant';
-		$setup_info['expressoCalendar']['tables'][]		=  'calendar_participant_status';
-		$setup_info['expressoCalendar']['tables'][]		=  'calendar_permission';
-		$setup_info['expressoCalendar']['tables'][]		=  'calendar_repeat';
-		$setup_info['expressoCalendar']['tables'][]		=  'calendar_signature';
-        $setup_info['expressoCalendar']['tables'][]		=  'calendar_signature_alarm';
-		$setup_info['expressoCalendar']['tables'][]		=  'module_preference';
-        $setup_info['expressoCalendar']['tables'][]		=  'calendar_to_calendar_object';
-				
+	$setup_info['expressoCalendar']['tables'][]		=  'attachment';
+	$setup_info['expressoCalendar']['tables'][]		=  'calendar_attach';
+	$setup_info['expressoCalendar']['tables'][]		=  'calendar_class'; 
+	$setup_info['expressoCalendar']['tables'][]		=  'calendar';
+	$setup_info['expressoCalendar']['tables'][]		=  'calendar_alarm';
+	$setup_info['expressoCalendar']['tables'][]		=  'calendar_ex_participant'; 
+	$setup_info['expressoCalendar']['tables'][]		=  'calendar_object'; 
+	$setup_info['expressoCalendar']['tables'][]		=  'calendar_object_type';
+	$setup_info['expressoCalendar']['tables'][]		=  'calendar_participant';
+	$setup_info['expressoCalendar']['tables'][]		=  'calendar_participant_status';
+	$setup_info['expressoCalendar']['tables'][]		=  'calendar_permission';
+	$setup_info['expressoCalendar']['tables'][]		=  'calendar_repeat';
+	$setup_info['expressoCalendar']['tables'][]		=  'calendar_signature';
+	$setup_info['expressoCalendar']['tables'][]		=  'calendar_signature_alarm';
+	$setup_info['expressoCalendar']['tables'][]		=  'module_preference';
+	$setup_info['expressoCalendar']['tables'][]		=  'calendar_to_calendar_object';
+	$setup_info['expressoCalendar']['tables'][]		=  'calendar_repeat_ranges';
+	$setup_info['expressoCalendar']['tables'][]		=  'calendar_repeat_occurrence';
+
 	$setup_info['expressoCalendar']['enable']		= 1;
 
Index: /trunk/prototype/services/iCal.php
===================================================================
--- /trunk/prototype/services/iCal.php	(revision 5682)
+++ /trunk/prototype/services/iCal.php	(revision 5715)
@@ -37,5 +37,5 @@
                     
                        $vevent = $ical->newComponent( 'vevent' );
-                        
+                                        
                        $vevent->setProperty( 'summary' , $v['summary'] );
                        $vevent->setProperty( 'description' , $v['description'] );
@@ -45,9 +45,36 @@
                        $timezone = new DateTimeZone('UTC');
                        $apTimezone = self::nomalizeTZID(( isset($v['timezone']) && $v['timezone'] != 'null' ) ? $v['timezone'] : $params['defaultTZI']);
-                         
+                       $apTimezoneOBJ = new DateTimeZone($apTimezone);
+                       
                        $sTime = new DateTime( '@'.(int)($v['startTime'] / 1000) , $timezone );                                    
-                       $sTime->setTimezone(new DateTimeZone($apTimezone));
+                       $sTime->setTimezone($apTimezoneOBJ);
                        $eTime = new DateTime( '@'.(int)($v['endTime'] / 1000) , $timezone );  
-                       $eTime->setTimezone(new DateTimeZone($apTimezone));
+                       $eTime->setTimezone($apTimezoneOBJ);
+                       
+                       if(isset($v['repeat']))
+                       {
+                           $repeat = array();
+                           
+                           foreach ($v['repeat'] as $ir => $rv) 
+                           {
+                               if($rv)
+                               {
+                                   if($ir == 'frequency')
+                                      $repeat['FREQ'] =  $rv;
+                                   else if($ir == 'endTime' )
+                                   {
+                                       $time = new DateTime( '@'.(int)($rv / 1000) , $timezone );                                    
+                                       $time->setTimezone($apTimezoneOBJ);
+                                       $repeat['until'] = $time->format(DATE_RFC822);
+                                   }
+                                   else if($ir == 'count')
+                                    $repeat[$ir] = $rv;
+                                   else if($ir !== 'schedulable' && $ir !== 'id' && $ir !== 'startTime')
+                                    $repeat[$ir] = explode(',', $rv);
+                               }
+                           }
+                          
+                           $vevent->setProperty('rrule' , $repeat);
+                       }
                        
                        if( isset($v['allDay']) && $v['allDay'] == 1 )
@@ -757,7 +784,14 @@
                     $repeat['schedulable'] = $eventID;
                     foreach($rrule as $i => $v)
-                       $repeat[strtolower($i)] = $v;
-
-                    //$interation['repeat://'.$repeatID] = $repeat;
+                    {
+                        if(strtolower($i) == 'freq')
+                            $repeat['frequency'] = $v;
+                        else if(strtolower($i) == 'until')
+                            $repeat['endTime'] = $v;
+                        else
+                            $repeat[strtolower($i)] = $v;
+                    }
+                    
+                    $interation['repeat://'.$repeatID] = $repeat;
                 }
 
Index: /trunk/prototype/Sync.php
===================================================================
--- /trunk/prototype/Sync.php	(revision 5514)
+++ /trunk/prototype/Sync.php	(revision 5715)
@@ -64,5 +64,5 @@
                     if( isset( $dt[$linkName] ) )
                     {
-                            if( $notArray = Controller::isConcept( $concept, $linkName ) )
+                            if( $notArray = Controller::hasOne( $concept, $linkName ) )
                                     $dt[$linkName] = array( $dt[$linkName] );
 
@@ -148,5 +148,5 @@
 
 		  $return[ $oldURI ] = !$tx['rollback'] ? $dt ? 
-				       array( 'id' => $tx['id'] ) : false : 'ROLLBACK';;
+				       array( 'id' => $tx['id'] ) : false : 'ROLLBACK';
 	  }
     }
Index: /trunk/prototype/config/repeat.ini
===================================================================
--- /trunk/prototype/config/repeat.ini	(revision 5514)
+++ /trunk/prototype/config/repeat.ini	(revision 5715)
@@ -1,5 +1,46 @@
 service = PostgreSQL
+PostgreSQL.concept = calendar_repeat
 
 [model.depends]
 schedulable = schedulable.repeat
 
+; [model.hasMany]
+; occurrences = repeatOccurrence.repeat
+
+[before.create]
+prepareRepeat = modules/calendar/interceptors/DBMapping.php
+; 
+[before.update]
+prepareRepeat = modules/calendar/interceptors/DBMapping.php
+
+[after.create]
+saveOccurrences = modules/calendar/interceptors/DBMapping.php
+
+[after.update]
+saveOccurrences = modules/calendar/interceptors/DBMapping.php
+
+[after.find]
+deepnessRepeat = modules/calendar/interceptors/DBMapping.php
+;reprepareRepeat = modules/calendar/interceptors/DBMapping.php
+
+[after.read]
+deepnessRepeat = modules/calendar/interceptors/DBMapping.php
+;reprepareRepeat = modules/calendar/interceptors/DBMapping.php
+
+[PostgreSQL.mapping]
+wkst = wkst
+byweekno = byweekno
+byminute = byminute
+bysecond = bysecond
+byyearday = byyearday
+bymonthday = bymonthday
+bysetpos = bysetpos
+byday = byday
+byhour = byhour
+interval = interval
+frequency = frequency
+endTime = until
+schedulable = object_id
+id = id
+count = count
+startTime = dtstart
Index: /trunk/prototype/config/schedulableToAttachment.ini
===================================================================
--- /trunk/prototype/config/schedulableToAttachment.ini	(revision 5514)
+++ /trunk/prototype/config/schedulableToAttachment.ini	(revision 5715)
@@ -2,5 +2,5 @@
 PostgreSQL.concept = calendar_attach
 
-[model.hasOne]
+[model.depends]
 schedulable = schedulable.attachments
 
Index: /trunk/prototype/config/repeatOccurrence.ini
===================================================================
--- /trunk/prototype/config/repeatOccurrence.ini	(revision 5715)
+++ /trunk/prototype/config/repeatOccurrence.ini	(revision 5715)
@@ -0,0 +1,10 @@
+service = PostgreSQL
+PostgreSQL.concept = calendar_repeat_occurrence
+
+[after.find]
+deepnessFindRepeatOccurrence = modules/calendar/interceptors/DBMapping.php
+
+[PostgreSQL.mapping]
+occurrence = occurrence
+repeat = repeat_id
+id = id
Index: /trunk/prototype/config/repeatRange.ini
===================================================================
--- /trunk/prototype/config/repeatRange.ini	(revision 5715)
+++ /trunk/prototype/config/repeatRange.ini	(revision 5715)
@@ -0,0 +1,8 @@
+service = PostgreSQL
+PostgreSQL.concept = calendar_repeat_ranges
+
+[PostgreSQL.mapping]
+rangeStart = range_start
+rangeEnd = range_end
+user = user_info_id
+id = id
Index: /trunk/prototype/config/schedulable.ini
===================================================================
--- /trunk/prototype/config/schedulable.ini	(revision 5514)
+++ /trunk/prototype/config/schedulable.ini	(revision 5715)
@@ -48,5 +48,5 @@
 transparent = transp
 class = class_id
-repeat = repeat
+;repeat = repeat
 rangeStart = range_start
 rangeEnd = range_end
Index: /trunk/prototype/config/attachment.ini
===================================================================
--- /trunk/prototype/config/attachment.ini	(revision 5592)
+++ /trunk/prototype/config/attachment.ini	(revision 5715)
@@ -1,7 +1,4 @@
 service = PostgreSQL
 PostgreSQL.concept = attachment
-
-[model.hasOne]
-schedulable = schedulable.attachments
 
 [before.create]
Index: /trunk/prototype/links.php
===================================================================
--- /trunk/prototype/links.php	(revision 5514)
+++ /trunk/prototype/links.php	(revision 5715)
@@ -16,4 +16,5 @@
     $concepts = array();
     $nestedLinks = array();
+    $hasOne = array();
 
     foreach( $link as $linkName => $linkTarget )
@@ -22,8 +23,11 @@
 	    $concepts[ $linkName ] = true;
 
+	 if( Controller::hasOne( $concept, $linkName ) )
+	    $hasOne[ $linkName ] = true;
+
 	  $nestedLinks[ $linkName ] = Controller::links( $concept, $linkName );
     }
 
-    $return[ $target ] = array( 'concepts' => $concepts, 'links' => $link, 'nestedLinks' => $nestedLinks );
+    $return[ $target ] = array( 'concepts' => $concepts, 'links' => $link, 'nestedLinks' => $nestedLinks, 'hasOne' => $hasOne );
 }
 
Index: /trunk/prototype/modules/calendar/interceptors/DBMapping.php
===================================================================
--- /trunk/prototype/modules/calendar/interceptors/DBMapping.php	(revision 5682)
+++ /trunk/prototype/modules/calendar/interceptors/DBMapping.php	(revision 5715)
@@ -7,22 +7,21 @@
 class DBMapping extends Helpers {	
            
-    public function encodeCreateSchedulable( &$uri , &$params , &$criteria , $original ){			
-        $params['type_id'] = EVENT_ID;
-	
-	
-		if(!is_numeric($params['startTime']) )
-			$params['startTime'] =  strtotime( $params['startTime'] . ' ' .$params['timezone']).'000';
+    public function encodeCreateSchedulable( &$uri , &$params , &$criteria , $original ){
+	$params['type_id'] = EVENT_ID;
+
+	if(!is_numeric($params['startTime']) )
+	  $params['startTime'] =   self::parseTimeDate( $params['startTime'], $params['timezone'] ); 
 		
-		if (!is_numeric($params['endTime'])){
-			$params['endTime'] =   strtotime( $params['endTime'] . ' ' .$params['timezone']).'000';
-			
-			if($params['allDay'])
-				$params['endTime'] =  $params['endTime']  + 86400000;
-		}
+	if (!is_numeric($params['endTime'])){
+	  $params['endTime'] =    self::parseTimeDate( $params['endTime'], $params['timezone'] ); 
+
+	  if($params['allDay'])
+	    $params['endTime'] =  $params['endTime']  + 86400000;
+	}
     //        if( !isset( $new['repeat'] ))
     //            $new['range_end'] = '7287926400'; // 12/12/2200
     //        else
             $params['rangeEnd'] = $params['endTime'];
-			$params['rangeStart'] =  $params['startTime'];
+	    $params['rangeStart'] =  $params['startTime'];
 
             ///////////////////////////////////////////////////////////////////
@@ -32,6 +31,9 @@
             $params['type'] = EVENT_ID;
             $params['uid'] = isset($params['uid']) ? $params['uid'] : $this->_makeUid();
-            
-        }	
+    }
+
+    static function parseTimeDate($time, $timezone){
+	return strtotime( $time . ' ' .$timezone).'000';         
+   }	
 		
     public function encodeCreateAlarm( &$uri , &$params , &$criteria , $original ){
@@ -89,17 +91,240 @@
            if(isset($params['isExternal']) && $params['isExternal'] == '1')
                 $uri['service'] = 'PostgreSQL'; 
-    }  
+    }
+
+    public function prepareRepeat(&$uri , &$params , &$criteria , $original ){
+
+	  $timezone = Controller::read( array( 'concept' => 'schedulable', 'id' => $params['schedulable'] ), array('timezone') );
+	  $params['startTime'] = self::parseTimeDate( $params['startTime'], $timezone['timezone'] );
+	  $params['endTime'] = self::parseTimeDate( $params['endTime'], $timezone['timezone'] );
+    }
       
-   public function findSchedulable( &$uri , &$params , &$criteria , $original )
+    public function findSchedulable( &$uri , &$params , &$criteria , $original )
    {
        if(isset($criteria['filter'][3][1]) && $criteria['filter'][3][1] == 'calendar')
        {
-         $select = 'calendar_object.id as id ,calendar_object.cal_uid as "uid" , calendar_object.type_id as "type", calendar_object.dtstart as "startTime", calendar_object.summary as "summary", calendar_object.description as "description", calendar_object.dtend as "endTime" , calendar_object.location as "location", calendar_object.allday as "allDay", calendar_object.transp as "transparent", calendar_object.class_id as "class", calendar_object.repeat as "repeat", calendar_object.range_start as "rangeStart",calendar_object.range_end as "rangeEnd", calendar_object.last_update as "lastUpdate", calendar_object.dtstamp as "dtstamp", calendar_object.sequence as "sequence",  calendar_object.tzid as "timezone" ,calendar_to_calendar_object.calendar_id as calendar';
-         $sql = " SELECT $select FROM calendar_to_calendar_object , calendar_object WHERE (range_start >= '".$criteria['filter'][1][2]."' AND range_end <= '".$criteria['filter'][2][2]."' AND calendar_to_calendar_object.calendar_id IN ('".  implode('\',\'', $criteria['filter'][3][2])."')) AND calendar_to_calendar_object.calendar_object_id = calendar_object.id";
-         $params = Controller::service('PostgreSQL')->execResultSql($sql);
+	  $start = $criteria['filter'][1][2];
+	  $end = $criteria['filter'][2][2];
+
+         $sql = ' SELECT calendar_object.id as id ,calendar_object.cal_uid as "uid", calendar_object.type_id as "type", calendar_object.dtstart as "startTime", calendar_object.summary as "summary", calendar_object.description as "description", calendar_object.dtend as "endTime" , calendar_object.location as "location", calendar_object.allday as "allDay", calendar_object.transp as "transparent", calendar_object.class_id as "class", calendar_object.repeat as "repeat", calendar_object.range_start as "rangeStart",calendar_object.range_end as "rangeEnd", calendar_object.last_update as "lastUpdate", calendar_object.dtstamp as "dtstamp", calendar_object.sequence as "sequence",  calendar_object.tzid as "timezone" ,calendar_to_calendar_object.calendar_id as calendar FROM calendar_to_calendar_object , calendar_object WHERE (range_start >= \''.$start.'\' AND range_end <= \''.$end.'\' AND calendar_to_calendar_object.calendar_id IN (\''.  implode('\',\'', $criteria['filter'][3][2]).'\')) AND calendar_to_calendar_object.calendar_object_id = calendar_object.id';
+         
+	 $params = Controller::service('PostgreSQL')->execResultSql($sql);
          $params = self::deepnessFindEvent( &$uri , &$params , &$criteria , $original);
+
+	 $occ = self::checkOccurrences( $criteria['filter'][1][2], $criteria['filter'][2][2], intval($criteria['deepness']) + 1 );
+
+	 if( $occ )
+	    $params = array_merge( $params, $occ );
+
          return false;
        }
    }
+
+  public function deepnessFindRepeatOccurrence( &$uri , &$result , &$criteria , $original )
+  {
+
+    if( !isset($criteria['deepness']) || $criteria['deepness'] == 0 )
+	  return;
+
+      foreach( $result as $i => &$res )
+	  if( isset($res['repeat']) )
+	      $res['repeat'] = Controller::read( array( 'concept' => 'repeat', 'id' => $res['repeat'] ), false, array( 'deepness' => intval( $criteria['deepness'] ) - 1 ) );
+  }
+
+  public function deepnessRepeat( &$uri , &$result , &$criteria , $original )
+  {
+
+      if( !isset($criteria['deepness']) || $criteria['deepness'] == 0 )
+	  return;
+
+	$result['schedulable'] = Controller::find( array( 'concept' => 'schedulable' ), false, array( 'filter' => array( '=', 'id', $result['schedulable'] ), 'deepness' => intval( $criteria['deepness'] ) - 1 ) );
+	$result['schedulable'] = $result['schedulable'][0];
+  }
+
+public function saveOccurrences( &$uri , &$result , &$criteria , $original ){
+
+	$ranges = Controller::find( array( 'concept' => 'repeatRange' ), array( 'rangeStart', 'rangeEnd' ),  array( 'filter' => array( '=', 'user', Config::me("uidNumber") ) ) );
+
+	if( !is_array( $ranges ) || !isset( $ranges[0]['rangeStart'] ) || !isset( $ranges[0]['rangeEnd'] ) )
+	    return;
+
+	if( isset( $result['id'] ) )
+	     $id = $result['id'];
+	else
+	     $id = $uri['id']; 
+
+	$repeat = Controller::read( array( 'concept' => 'repeat', 'id' => $id ) );
+
+	unset( $repeat['schedulable'] );
+	unset( $repeat['id'] );
+
+	$params = self::decodeRepeat( $repeat, $ranges[0]['rangeStart'], $ranges[0]['rangeEnd'] );
+
+	Controller::delete( array( 'concept' => 'repeatOccurrence' ), false, array( 'filter' => array( '=', 'repeat', $id ) ) );
+
+	if( !empty($params) )
+	    Controller::service('PostgreSQL')->execResultSql( "INSERT INTO calendar_repeat_occurrence(repeat_id,occurrence)VALUES('".$id."', '".implode( "'),('".$id."','", $params )."')" );
+
+    }
+
+    public function checkOccurrences( $start, $end, $deep ){
+
+	$ranges = Controller::find( array( 'concept' => 'repeatRange' ), array( 'rangeStart', 'rangeEnd' ),  array( 'filter' => array( '=', 'user', Config::me("uidNumber") ) ) );
+	$ranges = $ranges[0];
+
+	$origStart = $start;
+	$origEnd = $end;
+
+	if( $initialized = (isset($ranges['rangeStart']) && isset($ranges['rangeEnd'])) )
+	{
+	    if( $ranges['rangeStart'] <= $start )
+		$start = false;
+	    if( $ranges['rangeEnd'] >= $end )
+		$end = false;
+	}
+
+	$repeats = self::findRepeats();
+
+	if( !is_array( $repeats ) || empty( $repeats ) )
+	    return( false );
+
+	$result = array();
+	$ids = array();
+
+	foreach( $repeats as $repeat )
+	{
+	    $ids[] = $id = $repeat['id']; unset( $repeat['id'] ); 
+
+	    if( !isset( $result[ $id ] ) )
+		$result[ $id ] = array();
+
+	    if( !$initialized )
+		$result[ $id ] = array_merge( $result[ $id ], self::decodeRepeat( $repeat, $start, $end ) );
+	    else
+	    {
+		if( $start )
+		    $result[ $id ] = array_merge( $result[ $id ], self::decodeRepeat( $repeat, $start, $ranges['rangeStart'] ) );
+
+		if( $end )
+		    $result[ $id ] = array_merge( $result[ $id ], self::decodeRepeat( $repeat, $ranges['rangeEnd'], $end ) );
+	    }
+
+	    if( empty( $result[ $id ] ) )
+		unset( $result[ $id ] );
+	}
+
+	if( $start || $end )
+	{
+	    Controller::begin( array( 'service' => 'PostgreSQL') );
+
+	    foreach( $result as $id => $res )
+		Controller::service('PostgreSQL')->execResultSql( "INSERT INTO calendar_repeat_occurrence(repeat_id,occurrence)VALUES('".$id."','".implode( "'),('".$id."', '", $res )."')" );
+
+	    $data = array();
+
+	    if( $start )
+		$data['rangeStart'] = $start;
+
+	    if( $end )
+		$data['rangeEnd'] = $end;
+
+	    if( !$initialized )
+		$data['user'] = Config::me( 'uidNumber' );
+
+	    Controller::call( ( $initialized ? 'replace' : 'create' ), array( 'concept' => 'repeatRange' ), $data, array( 'filter' => array( '=', 'user', Config::me('uidNumber') ) ) );
+
+	    Controller::commit( array( 'service' => 'PostgreSQL' ) );
+	}
+
+	$return = Controller::find( array( 'concept' => 'repeatOccurrence' ), false, array( 'filter' => array( 'AND', array( '>=', 'occurrence', $origStart ), array( '<=', 'occurrence', $origEnd ), array( 'IN', 'repeat', $ids ) ), 'deepness' => $deep ) );
+
+	if( !is_array( $return ) )
+	  return( false );
+
+	$result = array();
+	$params = array();
+
+	foreach( $return as $ret )
+	{
+	      $currentId = $ret['repeat']['schedulable']['id'];
+
+	      if( !isset( $result[ $currentId ] ) )
+	      {
+		    $result[ $currentId ] = $ret['repeat']['schedulable'];
+		    $result[ $currentId ][ 'occurrences' ] = array();
+  
+		    $calendarToCalendarObj = self::schedulable2calendarToObject( $currentId );
+
+		    $result[ $currentId ]['calendar'] = $calendarToCalendarObj[0]['calendar_id'];
+
+		    unset( $result[ $currentId ]['repeat'] );
+	      }
+      
+	      $result[ $currentId  ][ 'occurrences' ][] = $ret['occurrence'];
+
+	}
+
+	foreach( $result as $id => $res )
+	    $params[] = $res;
+
+	return( $params );
+    }
+
+    public static function findRepeats()
+    {
+	return Controller::service('PostgreSQL')->execResultSql( 'SELECT calendar_repeat.wkst as "wkst", calendar_repeat.byweekno as "byweekno", calendar_repeat.byminute as "byminute", calendar_repeat.bysecond as "bysecond", calendar_repeat.byyearday as "byyearday", calendar_repeat.bymonthday as "bymonthday", calendar_repeat.bysetpos as "bysetpos", calendar_repeat.byday as "byday", calendar_repeat.byhour as "byhour", calendar_repeat.interval as "interval", calendar_repeat.frequency as "frequency", calendar_repeat.until as "endTime", calendar_repeat.id as "id", calendar_repeat.count as "count", calendar_repeat.dtstart as "startTime" FROM calendar_repeat, calendar_participant WHERE calendar_repeat.object_id = calendar_participant.object_id AND calendar_participant.user_info_id = \''.Config::me('uidNumber').'\'' );
+    }
+	
+//HELPERS
+    public static function decodeRepeat( $repeat , $start , $end ) {
+
+    date_default_timezone_set( 'UTC' );
+
+    require_once ROOTPATH.'/plugins/when/When.php';
+
+    $r = new When();
+
+    if( $repeat['frequency'] === 'none' )
+	return( array() );
+
+    $start =  new DateTime( '@'.(int)( max( $start, $repeat['startTime']  ) / 1000 ), new DateTimeZone('UTC') );    
+
+    foreach($repeat as $rule => $value)
+    {
+	    if( !isset( $value ) || !$value || $value === "0" )
+		continue;
+
+            switch(strtolower($rule))
+            {
+		    case "starttime": break;
+		    case "frequency":
+			    $r->recur( $start, $value );
+			    break;
+		    case "endtime":
+                            $r->until( new DateTime( '@'.(int)( $value / 1000 ) ) );
+                            break;
+                    case "count": case "interval":  case "wkst":
+                            $r->$rule( $value );
+                            break;
+                    default :
+                            $r->$rule( !is_array( $value ) ? explode( ',' , $value ) : $value );
+                            break;
+            }
+    }
+
+    $return = array();
+
+    while($result = $r->next())
+    { 
+       $u = $result->format('U') * 1000;
+
+       if( $u  > $end ) //data da repetição atual maior que a data final da busca do usuario ?
+           break;
+
+      $return[] = $u;
+    }
+
+    return( $return );
+}
    
 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -200,5 +425,5 @@
      
 	 public function deepnessFindCalendarShared( &$uri , &$result , &$criteria , $original ){				
-		if(isset($original['criteria']['deepness']) && count($result) > 0){
+		if(isset($original['criteria']['deepness']) && $original['criteria']['deepness'] != '0' && count($result) > 0){
 			$calendarIds = array();
 			foreach($result as $key => $value)
@@ -234,5 +459,5 @@
     public function deepnessFindEvent( &$uri , &$result , &$criteria , $original ){		
 
-       if(isset($original['criteria']['deepness']))
+       if(isset($original['criteria']['deepness']) && $original['criteria']['deepness'] != 0)
        {
 			
@@ -286,16 +511,24 @@
 					
 					
-					
-					$attachmentRelation = Controller::find( array( 'concept' => 'schedulableToAttachment' ) , false ,array( 'filter' => array('=', 'schedulable'  ,  $v['id']) )); 
-					if(is_array($attachmentRelation)){
-						$attachments = array();
-						foreach($attachmentRelation as $key => $value)
-							if(isset($value['attachment']) || !!$value['attachment'])
-								$attachments[$key]  = $value['attachment'];
-						//Pega os anexos sem source
-						$result[$i]['attachments'] = Controller::find( array( 'concept' => 'attachment' ) , array('id', 'name', 'type', 'size') ,array( 'filter' => array('IN', 'id' , $attachments) )); 
-					}
-				
-				}               
+		    
+		    $attachmentRelation = Controller::find( array( 'concept' => 'schedulableToAttachment' ) , false ,array( 'filter' => array('=', 'schedulable'  ,  $v['id']) )); 
+		    if(is_array($attachmentRelation)){
+			    $attachments = array();
+			    foreach($attachmentRelation as $key => $value)
+				    if(isset($value['attachment']) || !!$value['attachment'])
+					    $attachments[$key]  = $value['attachment'];
+			    //Pega os anexos sem source
+			    $result[$i]['attachments'] = Controller::find( array( 'concept' => 'attachment' ) , array('id', 'name', 'type', 'size') ,array( 'filter' => array('IN', 'id' , $attachments) )); 
+		    }
+
+		    if(isset($result[$i]['repeat'])){
+		      $repeat = Controller::read( array( 'concept' => 'repeat', 'id' => $result[$i]['repeat'] ) );
+
+		      if( !is_array($repeat) )
+			  unset( $result[$i]['repeat'] );
+		      else
+			  $result[$i]['repeat'] = $repeat[0];
+		    }
+	    }               
                 
            }
@@ -309,5 +542,5 @@
     public function deepnessReadEvent( &$uri , &$result , &$criteria , $original ){		
        
-       if(isset($original['criteria']['deepness']))
+       if(isset($original['criteria']['deepness']) && $original['criteria']['deepness'] != 0)
        {
             if(isset($result['id']))
@@ -334,5 +567,5 @@
     public function deepnessReadParticipant( &$uri , &$result , &$criteria , $original ){		
        
-       if(isset($original['criteria']['deepness']))
+       if(isset($original['criteria']['deepness']) && $original['criteria']['deepness'] != 0)
        {
             if(isset($result['id']))
@@ -350,5 +583,5 @@
     public function deepnessFindParticipant( &$uri , &$result , &$criteria , $original ){		
        
-       if(isset($original['criteria']['deepness']))
+       if(isset($original['criteria']['deepness']) && $original['criteria']['deepness'] != 0)
        {
            foreach ($result as $i => $v)
@@ -369,5 +602,5 @@
     public function deepnessReadCalendarSignature( &$uri , &$result , &$criteria , $original ){		
        
-       if(isset($original['criteria']['deepness']))
+       if(isset($original['criteria']['deepness']) && $original['criteria']['deepness'] != 0)
             if(isset($result['calendar'])){
                 $result['calendar'] = Controller::read( array( 'concept' => 'calendar' , 'id' => $result['calendar'])); 
@@ -380,5 +613,5 @@
     public function deepnessFindCalendarSignature( &$uri , &$result , &$criteria , $original ){		
 
-	if(isset($original['criteria']['deepness']))
+	if(isset($original['criteria']['deepness']) && $original['criteria']['deepness'] != 0)
        {
            foreach ($result as $i => $v)
@@ -387,5 +620,5 @@
                     $result[$i]['calendar'] = Controller::read( array( 'concept' => 'calendar' , 'id' => $v['calendar']), false, false); 
 					$result[$i]['defaultAlarms'] = Controller::find( array( 'concept' => 'calendarSignatureAlarm' ) , false ,array( 'filter' => array('=', 'calendarSignature'  ,  $v['id']) ));    
-					//Caso não seja o dono da agenda retorna o objeto permission com as acls
+					//Caso nÃ£o seja o dono da agenda retorna o objeto permission com as acls
 					if($result[$i]['isOwner'] == 0){
 						$permission = Controller::find( array( 'concept' => 'calendarToPermission'), false ,array( 'filter' => array('AND', array('=', 'calendar' ,  $v['calendar']), array('=', 'user', Config::me('uidNumber') ) ) ) ); 
@@ -504,5 +737,5 @@
                      )));
             
-            return false; /* Mata o restante da execução */
+            return false; /* Mata o restante da execuÃ§Ã£o */
         } 
         
@@ -541,5 +774,5 @@
     public function createDefaultSignature( &$uri , &$result , &$criteria , $original ){
     		     
-    //Caso uma busca não retorne nenhum resultado e foi buscado pelas assinaturas do usuario logado apenas
+    //Caso uma busca nÃ£o retorne nenhum resultado e foi buscado pelas assinaturas do usuario logado apenas
     if(count($result) <= 0 && 
             ( $original['criteria']['filter'][0] == '=' &&
@@ -592,7 +825,7 @@
         else
         {
-         //Criaremos uma agenda parão
+         //Criaremos uma agenda parÃ£o
           $cal = array('name' => 'Calendario',
-                         'description' => 'Calendario Padrão',
+                         'description' => 'Calendario PadrÃ£o',
                          'timezone' =>  (date_default_timezone_get()) ? date_default_timezone_get() : 'America/Sao_Paulo',
                          'dtstamp' => time().'000'
@@ -681,5 +914,5 @@
                     continue;
                 
-                //Criação do ical
+                //CriaÃ§Ã£o do ical
                 $ical = null;
               	$ical = new vcalendar();
@@ -702,5 +935,5 @@
 				///////////////////////////////////////////////////////////////////////////
                 
-                //Criação do E-mail
+                //CriaÃ§Ã£o do E-mail
                 $mail = array();
                 $mail['isHtml'] = true;  
@@ -719,6 +952,6 @@
                                                         ),ROOTPATH.'/api/templates/notify_create_body.tpl');
                 
-                //TODO: Internacionalização do Subject
-                $mail['subject'] = 'Schedulableo do Calendário : '.$schedulable['summary'] .' @ '.date_format( $sTime , 'd/m/Y H:i') . ' - ' .  date_format( $eTime , 'd/m/Y H:i');
+                //TODO: InternacionalizaÃ§Ã£o do Subject
+                $mail['subject'] = 'Schedulableo do CalendÃ¡rio : '.$schedulable['summary'] .' @ '.date_format( $sTime , 'd/m/Y H:i') . ' - ' .  date_format( $eTime , 'd/m/Y H:i');
                 $mail['from'] =  $organizer['mail'];
                 $mail['to'] = $att[$i]['mail'];
@@ -759,74 +992,5 @@
         }
     }
-	
-//HELPERS
-    private static function decodeRepeat( $repeat , $start , $end ) {
-    require_once ROOTPATH.'/plugins/when/When.php';
-
-    $r = new When();
-    $r->recur( new DateTime( '@'.$start , new DateTimeZone('UTC') ), $repeat['frequency'] );
-
-    foreach($repeat as $rule => $value)
-    {                  
-            switch(strtoupper($rule))
-            {
-                    case "ENDTIME":
-                            $r->until( new DateTime( '@'.$value ) );
-                            break;
-                    case "COUNT":
-                            $r->count( $value );
-                            break;
-                    case "INTERVAL":
-                            $r->interval( $value );
-                            break;
-                    case "BYDAY":
-                            if( !is_array( $value ) )
-                                $value = explode( ',' , $value );
-                            $r->byday( $value );
-                            break;
-                    case "BYMONTHDAY":
-                           if( !is_array( $value ) )
-                                $value = explode(',' , $value );
-                            $r->bymonthday($value);
-                            break;
-                    case "BYYEARDAY":
-                              if( !is_array( $value ) )
-                                $value = explode(',', $value );
-                            $r->byyearday( $value );
-                            break;
-                    case "BYWEEKNO":
-                             if(!is_array( $value ))
-                                $value = explode( ',', $value );
-                            $r->byweekno( $value );
-                            break;
-                    case "BYMONTH":
-                             if( !is_array( $value ) )
-                                $value = explode( ',', $value );
-                            $r->bymonth( $value );
-                            break;
-                    case "BYSETPOS":
-                             if( !is_array( $value ) )
-                                $value = explode( ',' , $value );
-                            $r->bysetpos( $value );
-                            break;
-                    case "WKST":
-                            $r->wkst( $value );
-                            break;
-            }
-    }
-
-    $return = array();
-
-    while($result = $r->next())
-    { 
-       $u = $result->format('U');
-       if( $u  > $end ) //data da repetição atual maior que a data final da busca do usuario ?
-           break;
-
-      $return[] =  $u;
-    }
-
-    return $return;
-}
+
     private function _makeUid() {
 
@@ -888,5 +1052,5 @@
     private static function schedulable2calendarToObject($Schedulable)
     {
-      return Controller::service('PostgreSQL')->execResultSql('SELECT calendar_to_calendar_object.id as calendar_to_calendar_Object , calendar.name as calendar_name ,calendar.location as calendar_location FROM calendar_to_calendar_object , calendar , calendar_signature' 
+      return Controller::service('PostgreSQL')->execResultSql('SELECT calendar_to_calendar_object.id as calendar_to_calendar_Object , calendar.name as calendar_name ,calendar.location as calendar_location, calendar.id as calendar_id FROM calendar_to_calendar_object , calendar , calendar_signature' 
                 .' WHERE calendar_signature.user_uidnumber = '.$_SESSION['wallet']['user']['uidNumber']
                 .' AND calendar_signature.is_owner = 1'
Index: /trunk/prototype/modules/calendar/export.php
===================================================================
--- /trunk/prototype/modules/calendar/export.php	(revision 5514)
+++ /trunk/prototype/modules/calendar/export.php	(revision 5715)
@@ -54,5 +54,11 @@
 		$event['attachments'] = Controller::find( array( 'concept' => 'attachment' ) , false ,array( 'filter' => array('IN', 'id' , $attachments) )); 
 	}
-		
+        
+    $repeat = Controller::find( array( 'concept' => 'repeat' ) , false ,array( 'filter' => array('=', 'schedulable'  ,  $event['id']) ));    
+        
+    if(is_array($repeat))
+        $event['repeat'] = $repeat[0];
+
+     
     $ics = Controller::format( array( 'service' => 'iCal' ) , array($event) , array('defaultTZI' => $event['timezone']) );
     
Index: /trunk/prototype/modules/calendar/js/calendar.codecs.js
===================================================================
--- /trunk/prototype/modules/calendar/js/calendar.codecs.js	(revision 5652)
+++ /trunk/prototype/modules/calendar/js/calendar.codecs.js	(revision 5715)
@@ -2,5 +2,5 @@
   
     init: function(){
-		this.moduleName = 'expressoCalendar';
+		this.moduleName = 'expressoCalendar'; 
 		this.me = DataLayer.dispatch( "me" );
 		
@@ -9,5 +9,5 @@
 		this.isDaylightSaving = Timezone.daylightSaving;
 		this.load();      
-    },
+    },             
   
     load: function(){
@@ -564,8 +564,9 @@
 				return returns;
 			};
-						
+								
 		    return {
 			    "class": objEvent["class"],
 			    id: objEvent.id,
+			    repeat: encodeRepeat( objEvent.repeat ),
 			    location: objEvent.location,
 			    category: objEvent.category,
@@ -605,7 +606,5 @@
 							receiveNotification : attend.receiveNotification,
 							alarms : $.map(attend.alarms || [], function( alarm ){
-								//TODO - Atualizar cach cliente em conceito aninhados de camada 2
-								var alarmEvent = DataLayer.get('alarm', alarm)
-								return !!alarmEvent ? alarmEvent: (null);
+								return DataLayer.get('alarm', alarm);
 							})
 						};
@@ -643,4 +642,5 @@
 			    me: !!participantInfo.user ? DataLayer.merge(participantInfo.user, me) : DataLayer.merge(this.isShared ? this.organizer :  me, {acl:  !this.isShared ? 'rowi' : Calendar.signatureOf[objEvent.calendar].permission.aclValues, delegatedFrom: 0, receiveNotification: 1}),
 				delegatedFrom: delegatedFrom,
+				
 				statusParticipants: statusParticipants
 			};
@@ -650,5 +650,85 @@
 });
 
-
+function decodeRepeat ( form ) {
+
+	var patati = {};
+	
+	if( form.repeatId )
+	    patati['id'] = form.repeatId;
+
+	patati['frequency'] = form.frequency;
+
+ 	patati['bymonthday'] = patati['byyearday'] = patati['byday'] = '';
+	
+	patati['interval'] = patati['endTime'] = patati['count'] = patati['startTime'] = 0;
+	
+	if( form.frequency === 'none' )
+	    return( patati );
+	
+	var day = [];
+
+	$("input[type=checkbox][name='repeatweekly[]']:checked").each(function() { 
+		day[ day.length ] = $(this).val();
+	});
+
+	patati['byday'] = day.join(',');
+
+	var formatString = ( typeof form.allDay !== "undefined" && !!form.allDay )? User.preferences.dateFormat+" HH:mm" : User.preferences.dateFormat + " " + User.preferences.hourFormat;
+
+	var date = Date.parseExact( form.startDate + (!!form.allDay ? " 00:00": " "+$.trim(form.startHour)) , formatString ).add( { days: 1 } ).toString('yyyy-MM-dd HH:mm:00');
+	
+	patati['startTime'] = date.toString('yyyy-MM-dd HH:mm:00');
+	
+	if( !patati['byday'] )
+	      switch(form.frequency) {
+	      case 'weekly':      
+		      break;
+	      case 'daily':
+		      break;
+	      case 'monthly':
+		      patati['bymonthday'] = date.getDate();
+		      break;
+	      case 'yearly':
+		      patati['byyearday'] = date.getDayOfYear();
+		      break;
+	      default :
+		      return patati;
+	      }
+
+	if (($(".endRepeat").val() == 'occurrences')) 
+		patati['count'] = $(".occurrencesEnd").val(); 
+	
+	if (($(".endRepeat").val() == 'customDate'))
+		patati['endTime'] = Date.parseExact( $(".customDateEnd").val() + (!!form.allDay ? " 00:00": " "+$.trim(form.endHour)) , formatString ).toString('yyyy-MM-dd HH:mm:00');
+	
+	patati['interval']  = $(".eventInterval").val();
+
+	/**
+	wkst = [ 'MO', 'TU', 'WE', 'TH', 'FR', 'SA', 'SU' ]
+	weekno = number
+	minute = number
+	second = number
+	yearday = number
+	monthday = number
+	setpos = number
+	day = number
+	hour = number
+	interval = number
+	frequency = [ 'monthly', 'daily', 'weekly', 'yearly', 'hourly', 'minutely', 'secondly' ]
+	endTime = milliseconds
+    */	  
+    return( patati );
+      
+}
+
+
+
+function encodeRepeat( repeat ){
+  
+	if( !repeat )
+	    return( false );
+
+	return DataLayer.get( 'repeat', repeat );
+}
 
 DataLayer.codec( "schedulable", "detail", {
@@ -674,5 +754,5 @@
 				  startTime: Date.parseExact(form.startDate + (!!form.allDay ? " 00:00": " "+$.trim(form.startHour)) , formatString ).toString('yyyy-MM-dd HH:mm:00'),
 				  endTime:  Date.parseExact(form.endDate + ( !!form.allDay ? " 00:00": " "+$.trim(form.endHour)), formatString ).toString('yyyy-MM-dd HH:mm:00'),  //+ (!!form.allDay ? 86400000 : 0) ,
-				  allDay: ( !!form.allDay ? 1 : 0 ),
+				  allDay: ( !!form.allDay ? 1 : 0 ),       
 			      id: form.idEvent,
 			      location: form.location,
@@ -685,4 +765,5 @@
 						return {attachment: attachment}
 				  }),
+			      repeat: this.decodeRepeat( form ),
 			      participants: $.map( form.attendee || [], function( attendee, i ){
 
@@ -722,45 +803,61 @@
     },
 
+
     encoder: function( evtObj ){
 	
-	if(!(!!evtObj))
-		return undefined;
-
-	var notArray = false;
-      
-	if( notArray = $.type(evtObj) !== "array" )
-	    evtObj = [ evtObj ];
-
-	var pref = User.preferences;
-
-	var res =  DataLayer.encode('schedulable:preview', evtObj);
-
-	if( !notArray ){
-	    var dates = {};
-
-	    for (var i=0; i < res.length; i++) {
-
-		    var startDate = Date.parseExact( res[i]['startDate'], User.preferences.dateFormat );
-		    var endDate   = Date.parseExact( res[i]['endDate'], User.preferences.dateFormat );
-
-		    var counter   = startDate.clone();
-
-		    while (counter.compareTo(startDate) == 0) {
-
-			    if (!dates[counter.toString(User.preferences.dateFormat)]) 
-					dates[counter.toString(User.preferences.dateFormat)] = { startDate:false, events:[] };
-			    if (!dates[counter.toString(User.preferences.dateFormat)].startDate) 
-					dates[counter.toString(User.preferences.dateFormat)].startDate = counter.toString(User.preferences.dateFormat);
-
-			    dates[counter.toString(User.preferences.dateFormat)].events.push(res[i]);
-			    counter.addDays(-1);
-		    } 
-	    }
-	    res = { events_list: dates,
-				count : res.length
-			};
-	}
-
-	return notArray ? res[0] : res;
+		if(!(!!evtObj))
+			return undefined;
+
+		var notArray = false;
+		  
+		if( notArray = $.type(evtObj) !== "array" )
+			evtObj = [ evtObj ];
+
+		var pref = User.preferences;
+
+		var res =  DataLayer.encode('schedulable:preview', evtObj);
+
+		if( !notArray ){
+			var dates = {};
+
+			for (var i=0; i < res.length; i++) {
+			  
+				var startDate = Date.parseExact( res[i]['startDate'], User.preferences.dateFormat );
+				var endDate   = Date.parseExact( res[i]['endDate'], User.preferences.dateFormat );
+			  
+				var duration = parseInt( endDate.getTime() ) - parseInt( startDate.getTime() );
+		
+				var occurrences = [ startDate.getTime() ];
+				
+				if( res[i].occurrences )
+				{
+				    occurrences = res[i].occurrences;
+				}
+
+				for( var ii = 0; ii < occurrences.length; ii++ )
+				{
+				    var currentDate = new Date( occurrences[ii] );
+				    var counter = currentDate.clone();
+				    
+				    var res2 = $.extend( {}, res[i], {'startDate': currentDate.toString( User.preferences.dateFormat ), 'endDate': new Date( occurrences[ii] + duration ).toString( User.preferences.dateFormat ) } );
+				  
+				    while (counter.compareTo( currentDate ) == 0) {
+
+					    if (!dates[counter.toString(User.preferences.dateFormat)]) 
+						    dates[counter.toString(User.preferences.dateFormat)] = { startDate:false, events:[] };
+					    if (!dates[counter.toString(User.preferences.dateFormat)].startDate) 
+						    dates[counter.toString(User.preferences.dateFormat)].startDate = counter.toString(User.preferences.dateFormat);
+
+					    dates[counter.toString(User.preferences.dateFormat)].events.push(res2);
+					    counter.addDays(-1);
+				    }      
+				}
+			}
+			res = { events_list: dates,
+					count : res.length
+				};
+		}
+
+		return notArray ? res[0] : res;
     }
 
@@ -823,89 +920,6 @@
 	    return( false );
 
-//       if( notArray = $.type(evtObj) !== "array" )
-// 	  evtObj = [ evtObj ];
-// 	alert( evtObj );
 	var filtered = evtObj;
-	
-	// repeat:{
-// 	  frequency: "weekly",
-// 	  endTime: Date.parse("+10 days").getTime(),
-// 	  interval: 3,
-// 	  byday: 3,
-// 	  bysecond: 3,
-// 	  byminute: 3,
-// 	  bymonthday: 3,
-// 	  byyearday: 3,
-// 	  byweekno: 3,
-// 	  bysetpos: 3,
-// 	  wkst: "monday"/*,
-// 	  duration: true*/
-//       }
-
-// 	$.each(evtObj, function( index, evt ){
-
-// 		alert( dump(!!evt.repeat) );
-
-// 		if( evt && !!evt.repeat && (evt.startTime < filter.end || (evt.repeat.endTime || 0) > filter.start ) )
-// 		{
-// // 		    var interval = evt.repeat.interval;
 // 
-// 		    var current = new Date( evt.startTime );
-// 		    var begin = new Date( filter.start );
-// 		    var end = new Date( filter.end );
-// 		    var offset = evt.endTime - evt.startTime;
-// 
-// 		    var ocurrence = [];
-// 
-// 		    while( Date.compare( current, begin ) !== 1 )
-// 			current = current.parse( "+" + evt.repeat.interval + " " + frequency + "s" );
-// 
-// 		    while( current.before( end ) && (ocurrence[ ocurrence.length ] = current) )
-// 			current = current.parse( "+" + evt.repeat.interval + " " + frequency + "s" );
-// 
-// 		    for( var i = 0; i < ocurrences.length; i++ )
-// 			filtered[ filtered.length ] = { URI: evt.URI,
-// 							summary: evt.summary,
-// 							start: new Date( ocurrences[i] ),
-// 							end: new Date( ocurrences[i] + offset ),
-// 							allDay: evt.allDay };
-// 
-// // 		    switch( evt.repeat.frequency )
-// // 		    {
-// // 		      case "yearly":   interval *= 12;
-// // 		      case "monthly":  interval *= 30; //TODO: get the month variant
-// // 		      case "weekly":   interval *= 7;
-// // 		      case "daily":    interval *= 24;
-// // 		      case "hourly":   interval *= 60;
-// // 		      case "minutely": interval *= 60; 
-// // 		      case "secondly": interval *= 1000;
-// // 		    }
-// // 		  
-// // 		    var rest = ( filter.start - evt.startTime ) % interval;
-// // 
-// // 		    var offset = evt.endTime - evt.startTime;
-// // 
-// // 		    if( rest < offset )
-// // 		    {
-// // 			var freq = Math.floor( offset - rest / interval );
-// // 
-// // 			
-// // 
-// // 			for( var i = 0; i < freq; i++ )
-// // 			{
-// // 			     var ocurrence = filter.start + rest + ( interval * i );
-// // 
-// // 			     
-// // 			}
-// // 
-// // 			
-// // 		    }
-// 		}
-
-// 		if( parseInt( evt.endTime ) > filter[1][0][2] || parseInt( evt.startTime ) < filter[1][1][2] )
-// 		    filtered[ filtered.length ] = evt;
-// 
-// 	});
-
 	var grouped = {};
 
@@ -922,5 +936,5 @@
 		var calendar = DataLayer.get('calendar', evt.calendar);
 		
-		var eventEditable = function(idEvent){
+		var eventEditable = function(idEvent, isRecurrence){
 			if(Calendar.signatureOf[calendar.id].isOwner == "1"){
 				var attendee = {};
@@ -928,7 +942,7 @@
 					attendee = DataLayer.get('participant', evt.participants[i]);
 						if(attendee.user == User.me.id)
-							return (attendee.acl.indexOf('w') >= 0 || attendee.acl.indexOf('o') >= 0 ) ? {selectable: true, className: 'fullcalendar-context-menu  event-id-'+idEvent} : {editable: false, selectable: true ,className: 'blocked-event-permision  fullcalendar-not-context-menu event-id-'+idEvent};
+							return (attendee.acl.indexOf('w') >= 0 || attendee.acl.indexOf('o') >= 0 ) ? {selectable: true, className: 'fullcalendar-context-menu  event-id-'+idEvent, editable: !isRecurrence} : { editable: false, selectable: true ,className: 'blocked-event-permision  fullcalendar-not-context-menu event-id-'+idEvent};
 				}
-				return {editable: false, className: 'blocked-event-permision  fullcalendar-not-context-menu event-id-'+idEvent,  selectable: true};
+				return {editable: false, className: 'blocked-event-permision  fullcalendar-not-context-menu event-id-'+idEvent,  selectable: true, disableDragging: isRecurrence };
 			}
 			else{
@@ -943,5 +957,5 @@
 				}				
 				return DataLayer.merge({
-					editable: aclSignature.acl['write'],
+					editable: aclSignature.acl['write'] && !isRecurrence,
 					disableResizing : (((aclSignature.acl['busy'] && !aclSignature.acl['write']) || (!aclSignature.acl['write'] && aclSignature.acl['read'])) ? true : false),
 					disableDragging  : (((aclSignature.acl['busy'] && !aclSignature.acl['write']) || (!aclSignature.acl['write'] && aclSignature.acl['read'])) ? true: false),
@@ -951,10 +965,21 @@
 			
 		}
+		
+		var duration = parseInt( evt.endTime ) - parseInt( evt.startTime ), isRepeat = false;
+		
+		var occurrences = [ evt.startTime ];
+		
+		if( evt.occurrences )
+		{
+		    isRepeat = true;
+		    occurrences = evt.occurrences;
+		}
 		  
-		grouped[ evt.calendar ].push( DataLayer.merge({ id: evt.URI || evt.id,
-						title: Encoder.htmlDecode(evt.summary),
-						start: Timezone.getDateCalendar(new Date(parseInt( evt.startTime )), calendar.timezone,  !!evt.DayLigth ? evt.DayLigth.calendar.startTime : Timezone.daylightSaving),
-						end:   Timezone.getDateCalendar(new Date(parseInt( evt.endTime ) - (!!parseInt(evt.allDay) ? 86400000 : 0)), calendar.timezone, !!evt.DayLigth ? evt.DayLigth.calendar.startTime : Timezone.daylightSaving),
-						allDay: parseInt( evt.allDay ) }, eventEditable(evt.id) ) );
+		for( var i = 0; i < occurrences.length; i++ )
+		    grouped[ evt.calendar ].push( DataLayer.merge({ id: evt.URI || evt.id,
+						    title: Encoder.htmlDecode(evt.summary),
+						    start: Timezone.getDateCalendar(new Date( parseInt( occurrences[i] ) ), calendar.timezone,  !!evt.DayLigth ? evt.DayLigth.calendar.startTime : Timezone.daylightSaving),
+						    end:   Timezone.getDateCalendar(new Date( parseInt( occurrences[i] ) + duration - (!!parseInt(evt.allDay) ? 86400000 : 0)), calendar.timezone, !!evt.DayLigth ? evt.DayLigth.calendar.startTime : Timezone.daylightSaving),
+						    allDay: parseInt( evt.allDay ) }, eventEditable(evt.id, isRepeat ) ) );
 	});
 
Index: /trunk/prototype/modules/calendar/js/helpers.js
===================================================================
--- /trunk/prototype/modules/calendar/js/helpers.js	(revision 5641)
+++ /trunk/prototype/modules/calendar/js/helpers.js	(revision 5715)
@@ -361,5 +361,161 @@
 			
 		}
-		
+
+	    DataLayer.render( 'templates/event_repeat.ejs', {event:objEvent}, function( repeatHtml ){
+
+			UI.dialogs.addEvent.find('#calendar_addevent_details3').html(repeatHtml);
+			$(".date").datepicker();
+		  
+			if(objEvent.repeat) 
+			{
+			     if( objEvent.repeat['id'] )
+			     {
+				$("[name='repeatId']:last").val( objEvent.repeat['id'] );
+			     }
+
+			     if( objEvent.repeat['frequency'] !== 'none' )
+			     {
+				if( objEvent.repeat['startTime'] && objEvent.repeat['startTime'] !== "0" )
+				{
+				      $("[name='startOptions'] [value='customDate']:last").attr( 'selected', 'selected' );
+				      $("[name='start']:last").val(new Date( parseInt(objEvent.repeat['startTime']) ).toString( User.preferences.dateFormat ) );
+				}
+				else
+				{
+				      $("[name='start']:last").val($("[name='startDate']:last").val());     
+				      $("[name='start']:last").readOnly=true;
+				      $("[name='start']:last").datepicker("disable");
+				}
+			      
+				$(".finish_event").removeClass("hidden");
+
+				if(objEvent.repeat['endTime'] && objEvent.repeat['endTime'] !== "0" ) 
+				{
+					//$("[name='occurrences']").addClass("hidden");
+					$(".customDateEnd").removeClass("hidden");
+							$(".endRepeat option[value='customDate']").attr('selected', 'selected')						
+					$(".customDateEnd").val( new Date( parseInt(objEvent.repeat['endTime']) )/*.setTimezoneOffset( Timezone.timezone( objEvent.timezone ) )*/.toString( User.preferences.dateFormat ) );  
+				}
+				else if (objEvent.repeat['count'] && objEvent.repeat['count'] !== "0" ) {
+					$(".endRepeat option[value='occurrences']").attr('selected', 'selected');						
+					$(".occurrencesEnd").removeClass("hidden");
+					$(".occurrencesEnd").val(objEvent.repeat['count']);						
+				}
+			      
+				switch ( objEvent.repeat['frequency'] )
+				{
+				    case "daily":
+					    $(".event-repeat-container:last").find(".repeat-in").find(".interval").html("Dia(s)");
+					    $(".frequency option[value='daily']").attr('selected', 'selected');
+					    break;
+				    case "weekly":
+					    $(".event-repeat-container:last").find(".repeat-in").find(".interval").html("Semana(s)");
+					    $(".frequency option[value='weekly']").attr('selected', 'selected');
+					    objEvent.repeat['interval'] ? $(".event-repeat-container:last").find(".repeat-in").find(".eventInterval").val(objEvent.repeat['interval']) : $(".event-repeat-container:last").find(".repeat-in").find(".eventInterval").val("0");
+					    
+					    $(".event-repeat-weekly").removeClass("hidden");
+					    
+					    var day = [];
+					    
+					    if( objEvent.repeat.byday )
+						day = objEvent.repeat.byday.split(',');
+					    
+					    for(i=0; i<day.length; i++) 
+						    $(".event-repeat-weekly [value='" + day[i] + "']").attr("checked","checked");
+					    
+					    break;
+				    case "monthly":
+					    $(".event-repeat-container:last").find(".repeat-in").find(".interval").html("Mes(s)");
+					    $(".frequency option[value='monthly']").attr('selected', 'selected')
+					    $(".event-repeat-monthly:last").removeClass("hidden").find("input[type=radio][name=repeatmonthyType]").click(function(){
+						    if($("input[type=radio][name=repeatmonthyType]:checked").val() == "1")
+							    $(".event-repeat-weekly:last").removeClass("hidden");
+						    else
+							    $(".event-repeat-weekly:last").addClass("hidden");
+					    });
+					    if($("input[type=radio][name=repeatmonthyType]:checked").val() == "1")
+						    $(".event-repeat-weekly:last").removeClass("hidden");
+					    else
+						    $(".event-repeat-weekly:last").addClass("hidden");
+					    break;
+				    case "yearly":
+					    $(".event-repeat-container:last").find(".repeat-in").find(".interval").html("Ano(s)");
+					    $(".frequency option[value='yearly']").attr('selected', 'selected')
+					    break;	
+				}
+			    }
+			}
+			else {
+				$(".endRepeat option[value='never']").attr('selected', 'selected');
+			}
+
+
+			$(".event-repeat-container:last").find(".repeat-in").find("[name=startOptions]").change(function(){                                       
+
+            if($(this).find("option:selected").val() == "Today"){
+                                $("[name='start']:last").val($("[name='startDate']:last").val());
+                                $("[name='start']:last").readOnly=true;
+                                $("[name='start']:last").datepicker("disable");
+                            }
+                            else{
+                                $("[name='start']:last").readOnly=false;
+                                $("[name='start']:last").datepicker("enable");
+                            }
+                        });
+                        $(".event-repeat-container:last").find(".repeat-in").find("[name=endOptions]").change(function(){                                       
+                            if($(this).find("option:selected").val() == "never"){
+                                $("[name='occurrences']").addClass("hidden");
+                                $("[name='end']:last").addClass("hidden");
+                            }
+                            else if($(this).find("option:selected").val() == "customDate"){
+                                $("[name='occurrences']").addClass("hidden");
+                                $("[name='end']:last").removeClass("hidden");    
+                            }
+                            else{
+                                $("[name='end']:last").addClass("hidden");
+                                $("[name='occurrences']").removeClass("hidden");                                        
+                            }
+                        });
+                        
+			$("[name='frequency']:last").change(function () {
+				$(".frequency-option").addClass("hidden");
+                                if($(this).val() == "none"){
+					$(".repeat-in").addClass("hidden");
+					return;
+				}else{
+                                    $(".repeat-in").removeClass("hidden");
+                                    $("[name='start']:last").val($("[name='startDate']:last").val());
+                                }
+                 
+				 
+				switch($(this).val()){
+                    case "daily":
+                        $(".event-repeat-container:last").find(".repeat-in").find(".interval").html("Dia(s)");
+                        break;
+					case "weekly":
+                        $(".event-repeat-container:last").find(".repeat-in").find(".interval").html("Semana(s)");
+						$(".event-repeat-weekly:last").removeClass("hidden");
+						break;
+					case "monthly":
+                        $(".event-repeat-container:last").find(".repeat-in").find(".interval").html("Mes(s)");
+						$(".event-repeat-monthly:last").removeClass("hidden").find("input[type=radio][name=repeatmonthyType]").click(function(){
+							if($("input[type=radio][name=repeatmonthyType]:checked").val() == "1")
+								$(".event-repeat-weekly:last").removeClass("hidden");
+							else
+								$(".event-repeat-weekly:last").addClass("hidden");
+						});
+                        if($("input[type=radio][name=repeatmonthyType]:checked").val() == "1")
+                            $(".event-repeat-weekly:last").removeClass("hidden");
+						else
+                            $(".event-repeat-weekly:last").addClass("hidden");
+					    break;
+                    default:
+                        $(".event-repeat-container:last").find(".repeat-in").find(".interval").html("Ano(s)");
+                        break;
+				}
+				
+			});
+		});
+
 	    UI.dialogs.addEvent.find('.calendar_addevent_details_lnk_timezone').click(function(e){
 		    $(this).addClass('hidden');
@@ -627,5 +783,5 @@
 					var user = DataLayer.get('user', ["=", "mail", $(this).val()]);
 					if(!!user && user[0].id)
-						attendees[user[0].id].name  = user[0].name;
+						attendees[user[0].id] = { name: user[0].name };
 					
 					/**
Index: /trunk/prototype/modules/calendar/templates/event_repeat.ejs
===================================================================
--- /trunk/prototype/modules/calendar/templates/event_repeat.ejs	(revision 5341)
+++ /trunk/prototype/modules/calendar/templates/event_repeat.ejs	(revision 5715)
@@ -1,9 +1,11 @@
 <fieldset id="calendar_event_repeat_form" class="event-repeat-container">
 	<legend class="hidden">Repetição do evento</legend>
+	<input type="hidden" name="repeatId"/>
 	
 	<p class="input-group">
 		<label for="frequency">Repetição:</label>
-		<select name="frequency">
-			<option value="dayly">Diária</option>
+		<select name="frequency" class="frequency">
+			<option value="none">Sem repetição</option>
+			<option value="daily">Diária</option>
 			<option value="weekly">Semanal</option>
 			<option value="monthly">Mensal</option>
@@ -12,72 +14,73 @@
 	</p>
 	
-	<p class="input-group">
-		<label>Repete a cada:</label>
-		<!-- Dia -->
-		<input type="text" name="interval" class="tiny number"><label class=""> Dias</label>
-	</p>
-	
 	<!-- Semana e Mês -->
 
-	
-	<!-- Semana -->
-	<p class="input-group event-repeat-weekly hidden">   
-		<label>Repete</label>
-		<input type="checkbox" name="repeatweekly[]" value="SU">
-		<label for="repeatweekly[]">D</label>
-
-		<input type="checkbox" name="repeatweekly[]" value="MO">
-		<label for="repeatweekly[]">S</label>
-
-		<input type="checkbox" name="repeatweekly[]" value="TU">
-		<label for="repeatweekly[]">T</label>
-
-		<input type="checkbox" name="repeatweekly[]" value="WE">
-		<label for="repeatweekly[]">Q</label>
-
-		<input type="checkbox" name="repeatweekly[]" value="TH">
-		<label for="repeatweekly[]">Q</label>
-
-		<input type="checkbox" name="repeatweekly[]" value="FR">
-		<label for="repeatweekly[]">S</label>
-
-		<input type="checkbox" name="repeatweekly[]" value="SA">
-		<label for="repeatweekly[]">S</label>
-	</p>
-
 	<!-- Mês -->
-	<p class="input-group event-repeat-monthly hidden"> 
-		<label>Repete</label>
-		<input type="radio" name="repeatmonthyType">
+	<p class="input-group event-repeat-monthly hidden frequency-option"> 
+		<label>Mensalmente por </label>
+		<input type="radio" name="repeatmonthyType" value="0">
 		<label for="repeatmonthyType">dia do mês</label>
 
-		<input type="radio" name="repeatmonthyType">
+		<input type="radio" name="repeatmonthyType" value="1">
 		<label for="repeatmonthyType">dia da semana</label>
 	</p>
 	
-	<p>
-		<!--
-		<label for="start">Inicia em</label>
-		<input class="date" type="text" name="start">
-		-->
-		<input type="checkbox" name="neverEnds" checked="checked">
-		<label for="end_event">Evento nunca termina</label>
+	<!-- Semana -->
+	<p class="input-group event-repeat-weekly hidden frequency-option">   
+		<label>Toda </label>
+		<input type="checkbox" name="repeatweekly[]" value="SU">
+		<label for="repeatweekly[]">Domingo</label>
+
+		<input type="checkbox" name="repeatweekly[]" value="MO">
+		<label for="repeatweekly[]">Segunda</label>
+
+		<input type="checkbox" name="repeatweekly[]" value="TU">
+		<label for="repeatweekly[]">Terça</label>
+
+		<input type="checkbox" name="repeatweekly[]" value="WE">
+		<label for="repeatweekly[]">Quarta</label>
+
+		<input type="checkbox" name="repeatweekly[]" value="TH">
+		<label for="repeatweekly[]">Quinta</label>
+
+		<input type="checkbox" name="repeatweekly[]" value="FR">
+		<label for="repeatweekly[]">Sexta</label>
+
+		<input type="checkbox" name="repeatweekly[]" value="SA">
+		<label for="repeatweekly[]">Sabado</label>
 	</p>
-	<label class="hidden label_finish_event">Termina</label>
-	<p class="hidden input-group finish_event">
+	
+	<p class="input-group finish_event repeat-in hidden">
+		<!-- <span class="input-group">
+			<label for="start">A repetição inicia</label>
+                        <select name="startOptions" class="startOptions">
+                            <option value="Today">Hoje</option>
+                            <option value="customDate">Na Data Selecionada</option>
+                        </select>
+			<input class="date startDate" type="text" name="start" readonly>
+		</span> -->
+        </p>
+        <p class="input-group finish_event repeat-in hidden">
 		<span class="input-group">
-			<input type="radio" name="repeat_finish" value="date_fixed">
-			<label>Em</label> 
-			<input type="text" name="" class="date">
+			<label class="label_finish_event">A repetição</label>
+			<!--<input type="radio" name="repeat_finish" value="date_fixed">-->
+                        <select name="endOptions" class="endRepeat">
+                            <option value="never">Nunca termina</option>
+                            <option value="customDate">Termina na Data Selecionada</option>
+                            <option value="occurrences">Termina Após n Ocorrencias</option>
+                        </select>
+						<input type="text" name="end" class="date customDateEnd hidden">
+                        <input type="text" name="occurrences" class="tiny number occurrencesEnd hidden">
+			<label name="occurrences" class="hidden">Ocorrências</label>
 		</span>
-		
-		<span class="input-group">
-			<input type="radio" name="repeat_finish" value="occurrences">
-			<label>Após</label>
-			<input type="text" name="" class="tiny number">
-			<label>Ocorrências</label>
+        </p>
+        <p class="input-group finish_event repeat-in hidden">
+                <span class="input-group">
+			<label>Tendo intervalo de</label>
+			<input type="text" name="" class="tiny number eventInterval" value="0">
+			<label class="interval"></label>
 		</span>
-	</p>
-	<button class="test-recurrence" onclick="recurrence();">Gera a repetição então, vamo ver!</button>
+        </p>                
+	<!--<button class="test-recurrence" onclick="recurrence();">Gera a repetição então, vamo ver!</button>-->
 <!--    <label for="calendar_event_repeat_summary">Resumo:</label>
     <span>Semanal: cada quinta-feira<span>-->
Index: /trunk/prototype/modules/calendar/templates/event_add.ejs
===================================================================
--- /trunk/prototype/modules/calendar/templates/event_add.ejs	(revision 5652)
+++ /trunk/prototype/modules/calendar/templates/event_add.ejs	(revision 5715)
@@ -49,5 +49,5 @@
 	<ul>
 		<li><a href="#calendar_addevent_details2">Detalhes do evento</a></li>
-<!--		<li><a href="#calendar_addevent_details3">Repetir</a></li>-->
+		<li><a href="#calendar_addevent_details3">Repetir</a></li>
 		<li><a href="#calendar_addevent_details4">Lembretes</a></li>
 		<li><a href="#calendar_addevent_details5">Anexos</a></li>
@@ -104,9 +104,9 @@
 		
 	</fieldset>
-<!--	
+
 	<fieldset id="calendar_addevent_details3" class="tab-level2">
 		
 	</fieldset>
-	-->
+
 	<fieldset id="calendar_addevent_details4" class="tab-level2">
 		<legend class="hidden">Lembretes</legend>
Index: /trunk/prototype/api/datalayer.js
===================================================================
--- /trunk/prototype/api/datalayer.js	(revision 5615)
+++ /trunk/prototype/api/datalayer.js	(revision 5715)
@@ -136,4 +136,5 @@
     nestedLinks: {},
     concepts: {},
+    notArray: {},
     listeners: {},
     encoders: {},
@@ -388,10 +389,10 @@
 		    if( data[i][link] )
 		    {
-			var isConcept = false;
-		      
-			if( isConcept = this.isConcept( concept, link ) )
+			var notArray2 = false;
+
+			if( notArray2 = this.hasOne( concept, link ) )
 			    data[i][link] = [ data[i][link] ];
 
-			var _this = this;
+			var _this = this, dependency = this.isDependency( concept, link );
 
 			$.each( data[i][link], function( ii, el ){
@@ -404,5 +405,5 @@
 				//removido pois o mesmo esta gerando inconsistencia em tudo
 // 				if( DataLayer.isConcept( links[link], nestedLinks[link] ) )
-				if( isConcept )
+				if( !DataLayer.hasOne( links[link], nestedLinks[link] ) )
 				{
 				    el[ nestedLinks[link] ] = el[ nestedLinks[link] ] || [];
@@ -413,5 +414,5 @@
 
 				if( isRef && ( !current[ key ] || !current[ key ][ link ] || 
-				               (isConcept ? current[ key ][ link ] !== el.id : !$.inArray( el.id, current[ key ][ link ] )) ) )
+				               (notArray2 ? current[ key ][ link ] !== el.id : !$.inArray( el.id, current[ key ][ link ] )) ) )
 				{
 				    updateSet[ links[link] ] = updateSet[ links[link] ] || [];
@@ -422,5 +423,5 @@
 			    });
 
-			if( isConcept )
+			if( notArray2 )
 			    data[i][link] = data[i][link][0];
 		    }
@@ -489,5 +490,5 @@
 		    continue;
 
-		if( isConcept = this.isConcept( concept, link ) )
+		if( this.hasOne( concept, link ) )
 		    current[i][link] = [ current[i][link] ];
 
@@ -972,4 +973,6 @@
 
 	    this.links[ concept ] =  result['links'] || {};
+	    
+	    this.notArray[ concept ] = result['hasOne'] || {};
 
 	   this.nestedLinks[ concept ] = result['nestedLinks'] || {};
@@ -985,5 +988,5 @@
     },
     
-    isConcept: function( concept, attr ){
+    isDependency: function( concept, attr ){
       
 	if( typeof this.concepts[concept] === "undefined" )
@@ -993,4 +996,14 @@
 
 	return !!this.concepts[ concept ][ attr ];
+    },
+    
+    hasOne: function( concept, attr ){
+      
+	if( typeof this.notArray[concept] === "undefined" )
+	{
+	    this.links( concept );
+	}
+
+	return !!this.notArray[ concept ][ attr ];
     },
     
@@ -1112,5 +1125,5 @@
       
 	for( var key in base )
-	    if( this.storage.filter( base[key], this.copy( filter ) ) )
+	    if( this.storage.filter( base[key], filter ) )
 		filtered[ filtered.length ] = key;
 
@@ -1125,8 +1138,8 @@
 
     
-    compare: function( operator, b, t ){
+    compare: function( operator, base, test ){
       
-	var base = this.converterType(b);
-	var test = this.converterType(t);
+	base = this.converterType(base);
+	test = this.converterType(test);
 	 
     switch( operator ){
@@ -1145,5 +1158,5 @@
 	case '<':  return ( base >  test );
 	
-	default: return false;
+	default: return true;
 	}
       
@@ -1164,12 +1177,12 @@
 
 	if( !filter || !result )
-	  return DataLayer.copy( result || false );
-
-	var keys = [];
-
-	if( notArray = $.type(filter) === "string" )
-	    keys = [ filter ];
-	else if( $.type(filter) !== "array" )
-		keys = this.filter( result, filter.filter, filter.criteria );
+	  return( result || false );
+
+	var keys = DataLayer.copy( filter );
+
+	if( notArray = $.type(keys) === "string" )
+	    keys = [ keys ];
+	else if( $.type(keys) !== "array" )
+		keys = this.filter( result, keys.filter, keys.criteria );
 
 	var res = [];
@@ -1178,5 +1191,5 @@
 	    res[ res.length ] = result[keys[i]];
 
-	return DataLayer.copy( notArray ? res[0] || false : res.length ? res : false );
+	return( notArray ? res[0] || false : res.length ? res : false );
     },
 
@@ -1192,5 +1205,5 @@
 	get: function( key ){
 
-	    return this.cache[key];
+	    return DataLayer.copy( this.cache[key] );
 
 	},
Index: /trunk/prototype/api/newcontroller.php
===================================================================
--- /trunk/prototype/api/newcontroller.php	(revision 5437)
+++ /trunk/prototype/api/newcontroller.php	(revision 5715)
@@ -4,5 +4,5 @@
     define( 'ROOTPATH', dirname(__FILE__).'/..' );
 
-require_once(ROOTPATH.'/app/config.php');
+require_once(ROOTPATH.'/api/config.php');
 
 /**
@@ -24,4 +24,6 @@
 	static $config = array();
 	static $includes = array();
+	static $tx = array();
+	static $txID = 0;
 	static $wallet;
 
@@ -43,7 +45,7 @@
 
 	public static function clearAll()
-	{
+	    {
 	    return self::$cache->clearAll();
-	}
+	    }
 
 	public static function clear( $id )
@@ -52,30 +54,24 @@
 	}
 
-	public static function get( $id )
+	public static function check( $id )
 	{
 	    return self::$cache->get( $id );
 	}
 
-	public static function put( $id, $data, $expires, $compressed )
+	public static function store( $id, $data, $expires, $compressed )
 	{
 	    return self::$cache->put( $id, $data, $expires, $compressed );
 	}
 
-	public static function find( $concept, $filter, $options = false )
-	{
-	    if( isset($URI['id']) && $URI['id'] )
-		return self::read( $URI, $params, $options );
-
-	    return self::call( 'find', $URI, $params, $options );
-	}
-
-	public static function read( $concept, $id, $options = false )
-	{
-	    if( !is_string( $id ) )
-		return self::find( $concept, $id, $options );
-
-	    return self::call( 'read', $concept, $id, $options );
-	}
 	
+
+// 	public static function read( $concept, $id = false, $options = 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 )
 // 	{
@@ -86,13 +82,5 @@
 // 	}
 
-	public static function delete( $concept, $id = false, $options = 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 )
+	// 	public static function replace( $URI, $params, $criteria = false )
 // 	{
 // 	    if( isset($URI['id']) && $URI['id'] )
@@ -102,74 +90,319 @@
 // 	}
 
-	public static function update( $concept, $params, $filter = false, $options = false )
-	{
-	    if( !isset($URI['id']) || !$URI['id'] )
-		return self::replace( $URI, $params, $criteria );
-
-	    return self::call( 'update', $URI, $params, $criteria );
-	}
-
-	public static function create( $concept, $params, $filter = false, $options = false )
-	{
-	    return self::call( 'create', $concept, $params, $filter, $options );
-	}
-
-	public static function begin( $concept, $id, $options = false )
-	{
-	    return self::call( 'begin', $concept, $id, $options );
-	}
-
-	public static function commit( $concept, /*$id,*/ $params = false, $options = false )
-	{
-	    return self::call( 'commit', $concept, $id, $params, $options );
-	}
-
-	public static function rollback($concept, /*$id,*/ $options = false )
-	{
-	    return self::call( 'rollback', $URI, $params, $options );
-	}
-
-	public static function format( $type, $data, $options = false )
-	{
-	    return self::call( 'format', $type, $data, $options );
-	}
-
-	public static function parse( $type, $data, $options = false )
-	{
-	    return self::call( 'parse', $type, $data, $options );
-	}
-
-	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 find( $concept, $options )
+	{    
+	    return self::get( $options['filter'],  self::context( $options, array( 'concept' => $concept ) ) );
+	}
+
+	public static function delete( $concept, $id = false, $options = array() )
+	{
+	    return self::put( false, self::context( $options, array( 'concept' => $concept, 'id' => $id ) ) );
+	}
+
+	public static function update( $concept, $data, $id = false, $options = array() )
+	{
+	    return self::put( $data, self::context( $options, array( 'concept' => $concept, 'id' => $id ) ) );
+	}
+
+	public static function create( $concept, $data, $options = array() )
+	{
+	    return self::put( $data, self::context( $options, array( 'concept' => $concept ) ) );
+	}
+
+	public static function put( $data, $options )
+	{
+	    try
+	    {
+		$context = self::context( $options );
+
+		$txId = self::begin( $context['service'] );
+
+		if( $context['format'] )
+		    $data = self::parse( $data, $context['format'], $options );
+
+		if( !isset($options['concept']) )
+		{
+		    $return = array();
+
+		    for( $data as $concept => $dt )
+			 $return[] = self::put( $dt, array_merge( array( 'concept' => $concept ), $options ) );
+			
+		    return $return;
+		}
+
+
+		$model = self::$models[ $options['concept'] ];
+
+		$postpone = array();
+
+		if( $data )
+		{
+		    foreach( $model['hasMany'] as $linkName => $linkTarget )
+		    {
+			$postpone[$linkTarget] = $dt[$linkName];
+		    }
+		    foreach( $model['hasOne'] as $linkName => $linkTarget )
+		    {
+			if( isset( $dt[$linkName] ) && is_array( $dt[$linkName] ) )
+			    $dt[$linkName] = self::put( $dt[$linkName],  array_merge( array( 'concept' => $linkTarget ), $options ) );
+		    }
+		}
+
+		$method = 	 $dt ? isset( $dt['id'] ) ?
+				'update' : 'create' : 'delete';
+
+		$context['id'] = $dt ? isset( $dt['id'] ) ?
+				 $dt['id'] : false : $context['id'];
+
+		self::before( $concept.':'.$method, &$context, $options );
+		self::call( $method, $options, $dt );
+		self::after( $concept.':'.$method, &$context, $options );
+
+		$result = $context['result'];
+
+		if( !is_bool( $result ) && !is_string( $result ) && isset( $result['id'] ) )
+		      $context['id'] = $result['id'];
+
+		foreach( $postpone as $linkTarget => $dt )
+		      foreach( $dt as $ii => $value )
+		      {
+			  if( !is_array( $value ) )
+			    $value = array( 'id' => $value );
+
+			  $value[ $options['concept'] ] = $options['id'];
+
+			  self::put( $value, array_merge( array( 'concept' => $linkTarget ), $options ) );
+		      }
+
+		if( $txId )
+		    return self::commit( $options['service'], $txId );
+	    }
+	    catch( Exception $e )
+	    {
+		if( !self::fallback( $e ) )
+		    self::closeAll();
+
+		return( false );
+	    }
+	
+	    return( $options['id'] );
+	}
+
+	public static function context( $options, $custom = false )
+	{
+	    if( $service )
+		$options['service'] = $service;
+
+	    return $options;
+	}
+
+	public static function get( $filter, $options = false )
+	{
+	    return self::call( 'find', self::context( $options, array( 'filter' => $filter ) ) );
+	}
+
+	public static function connect( $service, $options )
+	{
+	    $result = self::call( 'open', self::context( $options, array( 'service' => $service ) ) );
+
+	    if( is_string( $result ) )
+		throw new Exception( $result );
+
+	    return( true );
+	}
+
+	public static function begin( $service, $txId = false, $options = false )
+	{
+	    $context = self::context( $options );
+
+	    $result = self::call( 'begin', $options );
+
+	    if( !$txId )
+		$txId = $result ? $result : self::$txID++;
+
+	    if( isset( self::$transactions[ $txId ] ) )
+		return( false );
+
+	    self::$transactions[ $txId ] = array( 'txID' => $txId );
+	    self::$transactions[ $service ][] =& self::$transactions[ $txId ];
+
+	    return( $txId );
+	}
+
+	public static function commit( $service, $txId = false, $options = false )
+	{
+	    $context = self::context( $options );
+
+	    $txs = self::$transactions[ $service . ( $txId ? '.'.$txId : '' ) ];
+
+	    if( !is_array( $txs ) ) $txs = array( $txs );
+
+	    $return = array();
+
+	    foreach( $txs as $tx )
+	    {
+		$txID = $tx['txID'];
+
+		$result = false;
+
+		if( !$options || !$options['rollback'] )
+		    $result = self::call( 'commit', $context, $tx );
+
+		if( !$result )
+		    $result = self::call( 'rollback', $context, $tx );
+
+		$return[ $txID ] = $result;
+
+		unset( self::$transactions[ $txID ] );
+	    }
+
+	    return( $txId ? $return[ $txId ] : $return );
+	}
+
+	public static function rollback( $service, $txId = false, $options = array() )
+	{
+	    return self::commit( $service, $txId, self::context( $options, array( 'rollback' => true ) ) );
+	}
+
+	public static function fallback( $exception, $context ) // ver a melhor forma de tratar exceptions nesse caso
+	{
+	    if( !self::emmit( 'fallback', self::context( $context, array( 'exception' => $exception ) ), $exception ) )
+		error_log( $exception->getMessage() );
+ 
+	    return( true );
+	}
+
+	public static function format( $data, $service = false, $options = array() )
+	{
+	    return self::call( 'format', self::context( $options, array( 'service' => $service ) ), $data );
+	}
+
+	public static function parse( $data, $service = false, $options = array() )
+	{
+	    return self::call( 'parse', self::context( $options, array( 'service' => $service ) ), $data );
+	}
+
+	public static function before( $eventName, &$context, $extra = false )
+	{
+	    return self::emmit( 'before.'.$eventName, $context, $extra );
+	}
+
+	public static function after( $eventName, &$context, $extra = false )
+	{
+	    return self::emmit( 'after.'.$eventName, $context, $extra );
+	}
+
+	public static function emmit( $eventName, &$context, $extra = false )
+	{
+	    if( self::$listeners[ $eventName ] )
+		return( false );
+
+	    foreach( self::$listeners[ $eventName ] as $listen => $listener )
+	    {
+		 $return = $listener->$listen( $context, $extra );
+
+		 if( $return === false )
+		    return( true );
+
+		 $context = self::context( $context, array( 'return' => $return ) );
+	    }
+
+	    return( $return );
+	}
+
+	//TODO: Compatibilizar as configs relativas aos modulos, adicionando os mesmos nas options passadas
+	public static function call( $method, $options, $data = false ) //see how data fit in it
+	{
+	    try
+	    {
+		$context = self::context( $options, array( 'data' => $data ) );
+
+		$service = $context['service'];
+
+		if( $context['config'] )
+		    self::connect( $service, $context['config'] );
+
+		self::before( $service.'.'.$method, &$context, $options );
+
+		if( self::$services[ $service ] )
+		    switch( $method )
+		    { 
+			case 'find': $return = self::$services[ $service ]->find( $context['URI'], $context['properties'], $context['criteria'] ); break;
+
+			case 'read': $return = self::$services[ $service ]->read( $context['URI'], $context['properties']/*, $criteria*/ ); break;
+
+			case 'create': $return = self::$services[ $service ]->create( $context['URI'], $context['properties']/*, $criteria*/ ); break;
+
+			case 'delete': $return = self::$services[ $service ]->delete( $context['URI'], $context['properties']/*, $criteria*/ ); break;
+
+			case 'deleteAll': $return = self::$services[ $service ]->deleteAll( $context['URI'], $context['properties'], $context['criteria'] ); break;
+
+			case 'update': $return = self::$services[ $service ]->update( $context['URI'], $context['properties']/*, $criteria*/ ); break;
+
+			case 'replace': $return = self::$services[ $service ]->replace( $context['URI'], $context['properties'], $context['criteria'] ); break;
+
+			case 'begin': $return = self::$services[ $service ]->begin( $context['URI'] ); break;
+
+			case 'commit': $return = self::$services[ $service ]->commit( $context['URI'], $context['criteria'] ); break;
+
+			case 'rollback': $return = self::$services[ $service ]->rollback( $context['URI'], $context['criteria'] ); break;
+
+			case 'parse': $return = self::$services[ $service ]->parse( $context['properties'], $context['criteria'] ); break;
+
+			case 'analize': $return = self::$services[ $service ]->analize( $context['properties'], $context['criteria'] ); break;
+
+			case 'format': $return = self::$services[ $service ]->format( $context['properties'], $context['criteria'] ); break;
+
+			default : $return = self::$services[ $service ]->$method( $context['properties'], $context['criteria'] );
+		    }
+
+		$context['return'] = $return;
+
+		self::after( $service.'.'.$method, &$context, $options );
+	    }
+	    catch( Exception $e )
+	    {
+		if( !self::fallback( $e ) )
+		    self::closeAll();
+
+		return( false );
+	    }
+
+	    return( $context['return'] ); 
+	}
+
+// 	public static function URI( $className, $id = false, $service = false )
+// 	{
+// 	    return array( 'concept' => $className,
+// 			  'service' => $service ? $service : false, 
+// 			  'id' => $id ? $id : '' );
+// 	}
+
+	//TODO: Compatibilizar as configs relativas aos modulos, adicionando os mesmo nos parametros passados
+// 	public static function links( $concept = false )
+// 	{
+// 	    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, $moduleName = false )
+// 	{
+// 	    if( isset( self::$config[ $concept ] ) )
+// 		return( self::$config[ $concept ] );
+// 
+// 	    return( self::$config[ $concept ] = self::loadConfig( $concept, $moduleName ) );
+// 	}
 
 	public static function loadCache( $cacheType = 'Memory' )
@@ -178,14 +411,15 @@
 	    return new MemoryCache();
 	}
-	
-	public static function loadConfig( $className, $isService = false )
+
+	//TODO: Compatibilizar as configs relativas aos modulos, adicionando os mesmo nos parametros passados
+	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 );
+                $config = parse_ini_file( ROOTPATH.'/config/'.$fileName, true );
 
 		self::$cache->put( $fileName, $config );
@@ -196,8 +430,7 @@
 
 	public static function import( $path, $ext = ".php" )
-	{
-           
+	{ 
 	    if( !isset(self::$includes[$path]) )
-	    {
+	{
 		require_once( ROOTPATH.'/'.$path.$ext );
 		self::$includes[$path] = false;
@@ -208,9 +441,8 @@
 
 	public static function load( $path, $class = false )
-	{
-            
+	    { 
             if( $return = self::import( $path, "" ) )
 		return( $return );
-            
+
 	    if( !$class ){
 		preg_match( '/^\/?.*\/([^\/]+).php$/', $path, $class );
@@ -236,30 +468,6 @@
 	    {
 		//// Hack //// TODO: passar o init da sessÃ£o no login do expresso
-		if ( isset( $_COOKIE[ 'sessionid' ] ) ) 
-		      session_id( $_COOKIE[ 'sessionid' ] ); 
-                
-		@session_start();
-
-// 		if( !isset( $_SESSION['wallet'] ) )
-// 		{
-// 		    if( isset( $GLOBALS['phpgw_info'] ) )
-// 		    {
-// 				$_SESSION['wallet']['Sieve']['user']          = $GLOBALS['phpgw_info']['user']['account_lid'];
-// 				$_SESSION['wallet']['Sieve']['password']      = $GLOBALS['phpgw_info']['user']['passwd'];
-// 
-// 				$_SESSION['wallet']['Cyrus']['user']          = $GLOBALS['phpgw_info']['user']['account_lid'];
-// 				$_SESSION['wallet']['Cyrus']['password']      = $GLOBALS['phpgw_info']['user']['passwd'];
-// 
-// 				$_SESSION['wallet']['user']		      = $GLOBALS['phpgw_info']['user']['account_lid'];
-// 			// 			$_SESSION['wallet']['me']['password']      = $_SESSION['phpgw_info']['expressomail']['user']['passwd'];
-// 
-// 				$_SESSION['wallet']['PostgreSQL']['user']     = $GLOBALS['phpgw_info']['server']['db_user'];
-// 				$_SESSION['wallet']['PostgreSQL']['password'] = $GLOBALS['phpgw_info']['server']['db_pass'];
-// 				$_SESSION['wallet']['PostgreSQL']['dbname']   = $GLOBALS['phpgw_info']['server']['db_name'];
-// 		    }
-// 		    else
-// 			$_SESSION['wallet'] = array();
-// 		}
-                
+		Config::init();
+
                 if(isset($_SESSION['wallet']))
                     self::$wallet = $_SESSION['wallet'];
@@ -269,4 +477,14 @@
 	    return isset( self::$wallet[ $serviceName ] )? self::$wallet[ $serviceName ] : false;
 	}
+		
+	
+
+	public static function configure( $config, $newConfig )
+	{
+	    foreach( $newConfig as $key => $value )
+		$config[$key] = $value;
+
+	    return( $config );
+	    }
 
 	public static function dispatch( $dispatcher, $data, $optionsMap = false )
@@ -283,23 +501,25 @@
 	}
 
-	public static function loadAll( $configurable, $isService = false )
-	{
-	}
-
-	public static function connect( $service, $config )
-	{
-	    $result = $service->open( $config );
-
-	    if( is_string( $result ) )
-		throw new Exception( $result );
-
-	    return( true );
-	}
-
-	public static function open( $serviceName, $config = false )
-	{
-	    $service = self::$services[ $serviceName ];
-
-	    $srvConfig = array();
+	//TODO: Compatibilizar as configs relativas aos modulos, adicionando os mesmo nos parametros passados
+	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 );
+
+	    if( !isset(self::$config[ $serviceName ]['type']) )
+		self::$config[ $serviceName ]['type'] = 'service';
+
+	    self::import( 'api/'.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' ]) )
@@ -307,6 +527,6 @@
 	    if( $wallet = self::wallet( $serviceName ) )
 		$srvConfig = self::configure( $srvConfig, $wallet );
-	    if( $config )
-		$srvConfig = self::configure( $srvConfig, $config );
+	    if( $concept && isset(self::$config[ $concept ]['service.config']) )
+		$srvConfig = self::configure( $srvConfig, self::$config[ $concept ]['service.config'] );
 
 	    if( empty( $srvConfig ) )
@@ -315,41 +535,9 @@
 	    if( $service && self::$config[ $serviceName ]['type'] === 'service' )
 		self::connect( $service, $srvConfig );
-	}
-
-	public static function configure( $config, $newConfig )
-	{
-	    foreach( $newConfig as $key => $value )
-		$config[$key] = $value;
-
-	    return( $config );
-	}
-
-	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 );
-
-	    if( !isset(self::$config[ $serviceName ]['type']) )
-		self::$config[ $serviceName ]['type'] = 'service';
-
-	    self::import( 'app/'.self::$config[ $serviceName ]['type'] );   //TODO: Item 4
-
-	    self::$services[ $serviceName ] = self::load( self::$config[ $serviceName ]['path'],
-							  self::$config[ $serviceName ]['class'] );
-
-	    if( $concept && isset(self::$config[ $concept ]['service.config']) )
-		self::open( $serviceName, $self::$config[ $concept ]['service.config'] );
-	    else
-		self::open( $serviceName );
 
 	    return( self::$services[ $serviceName ] = $service );
 	}
 
+	//TODO: Compatibilizar as configs relativas aos modulos, adicionando os mesmo nos parametros passados
 	public static function interceptor( $method, $concept = false, $serviceName = false, $isService = false )
 	{
@@ -390,24 +578,43 @@
 	}
 
-	public static function fire( $eventType, $method, $params, $original, $isService = false )
-	{
-	    $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 );
-	}
+// 	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 );
+// 	}
 
 	/*
@@ -424,89 +631,26 @@
 	*/
 
-	public static function call( $method, $URI, $properties, $criteria = false, $service = false )
-	{
-	    try
-	    {
-		$original = $params = array( 'properties' => $properties, 
-				             'criteria' => $criteria, 
-					     'URI' => $URI,
-					     'service' => $service );
-
-		if( isset($params['URI']['concept']) )
-		    $params = self::fire( 'before', $method, $params, $original );
-
-		if( !$params['service'] )
-		{
-		    $isInternal = true;
-
-		    if( ( !isset($params['URI']['service']) || !$params['URI']['service'] ) && isset($params['URI']['concept']) )
-		    {
-			if( !isset(self::$config[ $URI['concept'] ]) )
-			    self::$config[ $URI['concept'] ] = self::loadConfig( $URI['concept'] );
-
-			$params['URI']['service'] = self::$config[ $URI['concept'] ][ 'service' ];
-		    }
-
-		    if( !isset($params['URI']['service']) )
-			return( false );
-
-		    $params['service'] = self::service( $params['URI']['service'], isset($params['URI']['concept']) ? $params['URI']['concept'] : false );
-		}
-
-		if( isset($params['URI']['service']) )
-		    $params = self::fire( 'before', $method, $params, $original, true );
-
-		if( $params['service'] )
-		    switch( $method )
-		    {
-			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'] ); break;
-
-			case 'rollback': $return = $params['service']->rollback( $params['URI'] ); 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']) )
-		    $params = self::fire( 'after', $method, $params, $original, true );
-
-		if( isset($URI['concept']) )
-		    $params = self::fire( 'after', $method, $params, $original );
-	    }
-	    catch( Exception $e )
-	    {
-		if( !self::fallback( $e ) )
-		    self::closeAll();
-
-		return( false );
-	    }
-
-	    return( empty($params['properties']) ? false : $params['properties'] );
-	}
-
-	public static function fallback( $exception )
-	{
-	    error_log( $exception->getMessage() );
-	    return( true );
+	//TODO: Compatibilizar as configs relativas aos modulos, adicionando os mesmo nos parametros passados
+	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 );
 	}
 }
Index: /trunk/prototype/api/controller.php
===================================================================
--- /trunk/prototype/api/controller.php	(revision 5637)
+++ /trunk/prototype/api/controller.php	(revision 5715)
@@ -27,4 +27,5 @@
 	static $tx = array();
 	static $isConcept = array();
+	static $hasOne = array();
 	static $txID = 0;
 	static $wallet;
@@ -161,4 +162,5 @@
 	    $links = array();
 	    self::$isConcept[ $concept ] = array();
+	    self::$hasOne[ $concept ] = array();
 
 	    if( isset(self::$config[ $concept ][ 'model.hasOne' ]) )
@@ -171,5 +173,5 @@
 
 		    $links[$linkName] = $target;
-		    self::$isConcept[ $concept ][ $linkName ] = true;
+		    self::$hasOne[ $concept ][ $linkName ] = true;
 		}
 	    if( isset(self::$config[ $concept ][ 'model.depends' ]) )
@@ -182,4 +184,5 @@
 
 		    $links[$linkName] = $target;
+		    self::$hasOne[ $concept ][ $linkName ] = true;
 		    self::$isConcept[ $concept ][ $linkName ] = true;
 		}
@@ -204,4 +207,12 @@
 
 	    return( isset(self::$isConcept[ $concept ][ $linkName ]) );
+	}
+
+	public static function hasOne( $concept, $linkName )
+	{ 
+	    if( !isset( self::$hasOne[ $concept ] ) )
+		self::links( $concept );
+
+	    return( isset(self::$hasOne[ $concept ][ $linkName ]) );
 	}
 
@@ -646,4 +657,8 @@
 
 		foreach( $postpone as $linkTarget => $dt )
+		{
+		      if( Controller::hasOne( $URI['concept'], $linkNames[ $linkTarget ] ) )
+			  $dt = array( $dt );
+
 		      foreach( $dt as $ii => $value )
 		      {
@@ -655,5 +670,5 @@
 			  self::put( array( 'concept' => $linkTarget ), $value, &$txIds );
 		      }
-
+		}
 		if( $commit )
 		{
