<?php
/*
Officity - Web application platform - Version 6.0 - 2011-07-05

François Dispaux, Boris Verdeyen, Thomas Hermant,
Jérémie Roy, Grégory Meurice, Abdelila Harbi, 
Marc Mignonsin, Jonathan Sanchez, Julien Gonzalez, Pierre Fouchez

Sushee and Officity is © Copyright 2011 Nectil SA.

`/sushee-source/sushee/common/searchoutputmanager.proto.php` is part of Officity.

Sushee is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Officity and Sushee are distributed in the hope that they will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Sushee. If not, see <http://www.gnu.org/licenses/>.
*/
require_once(dirname(__FILE__)."/../common/nectil_object.class.php");
require_once(dirname(__FILE__)."/../common/searchprofile.class.php");
require_once(dirname(__FILE__)."/../common/dependencies.class.php");
require_once(dirname(__FILE__)."/../common/nectil_object.class.php");
require_once(dirname(__FILE__)."/../common/searchprofile.class.php");
require_once(dirname(__FILE__)."/../common/console.class.php");
require_once(dirname(__FILE__)."/../common/comments.inc.php");
require_once(dirname(__FILE__)."/../common/categories.inc.php");
require_once(dirname(__FILE__)."/../common/properties.inc.php");
require_once(dirname(__FILE__)."/../common/dependencies.inc.php");
require_once(dirname(__FILE__)."/../common/infoxml.class.php");
require_once(dirname(__FILE__)."/../common/nectil_user.class.php");
require_once(dirname(__FILE__)."/../common/omnilinks.class.php");


/*
Caching resolved profiles (resolving = node transformed in a class). we can then get back the resolved profile knowing the node describing the profile
*/
class Sushee_ElementProfileFactory extends SusheeObject{
	
	var $profiles = array();
	
	function getProfile($node){
		$nodeID = $node->getUniqueID();
		if($this->profiles[$nodeID]){
			return $this->profiles[$nodeID];
		}else{
			$profile = new Sushee_ElementProfile($node);
			$this->profiles[$nodeID] = $profile;
			return $profile;
		}
	}
	
}
/*
This class defines what should be returned for an element (= resolved profile)
*/
class Sushee_ElementProfile extends SusheeObject{
	
	var $mode;
	var $get_owner;
	var $get_modifier;
	var $get_creator;
	var $get_weekdays;
	var $freelinks_config;
	var $get_info;
	var $desc_profile;
	var $desc_discarding;
	var $profileFields_by_module;
	var $get_dependencies;
	var $get_descriptions;
	var $get_categories;
	var $get_freelinks;
	var $get_comments;
	var $get_properties;
	var $get_omnilinks;
	var $path;
	var $xml;
	
	// named profile (publication, mini) <RETURN name="mini"/>
	function getPredefinedProfile($profile_name){
		$desc_profile = new DescriptionProfile();
		$this->name = $profile_name;
		$this->mode = 'normal';
		$this->get_owner = false;
		$this->get_modifier = false;
		$this->get_creator = false;
		$this->freelinks_config = array();
		$this->get_info = true;
		$this->desc_profile = $desc_profile;
		$this->get_dependencies = false;
		$this->get_descriptions = false;
		$this->get_categories = false;
		$this->get_freelinks = false;
		$this->get_comments = false;
		$this->get_properties = false;

		switch($profile_name){
			case 'mailingMedias':
			case 'publication':
				$this->get_descriptions=true;
				$this->get_categories=true;
				$this->get_dependencies=true;//mini!
				$this->dependencies_profile = new Sushee_ElementProfile('mini');
				break;
			case 'mini':
				$this->info_profile
					= new InfoProfile( 
	array('ID'=>true,'CREATORID'=>true,'MODIFIERID'=>true,'OWNERID'=>true,'GROUPID'=>true,'CREATIONDATE'=>true,'MODIFICATIONDATE'=>true,'CONTACTTYPE'=>true,'FIRSTNAME'=>true,'LASTNAME'=>true,'DENOMINATION'=>true,'CLIENTCODE'=>true,'EMAIL1'=>true,'TITLE'=>true,'ADDRESS'=>true,'POSTALCODE'=>true,'CITY'=>true,'STATEORPROVINCE'=>true,'COUNTRYID'=>true,'PHONE1'=>true,'MOBILEPHONE'=>true,'FAX'=>true,'PURPOSE'=>true,'BIRTHDAY'=>true,'GENDER'=>true,'PREVIEW'=>true,'WEBSITE'=>true,'LANGUAGEID'=>true) 
					);
				break;
			case 'complete':
				$this->get_descriptions=true;
				$this->get_categories=true;
				$this->get_dependencies=true;//mini!
				$this->dependencies_profile = new Sushee_ElementProfile('mini');
				$this->get_comments=true;
				$this->get_freelinks=true;//mini!
				$this->freelinks_config = array('profile_name'=>'mini');
				break;
			case 'descriptions_only':
				$this->get_info=false;
				$this->get_descriptions=true;
				break;
			case 'empty':
				break;
			case 'mailing_publication':
				$this->get_descriptions=true;
				$this->get_categories=true;
				$this->get_dependencies=true;//mini!
				$this->dependencies_profile = new Sushee_ElementProfile('mini');
				$this->get_creator=true;
				break;
			case 'mini_inbox':
				$this->info_profile = 
					new InfoProfile (
	array('ID'=>true,/*'CREATIONDATE'=>true,'MODIFICATIONDATE'=>true,*/'ACCOUNTID'=>true,'TYPE'=>true,'PRIORITY'=>true,'FROM'=>true,'TO'=>true,'SENDINGDATE'=>true,'RECEIVINGDATE'=>true,'ATTACHMENTS'=>true,'SUBJECT'=>true,'READ'=>true,'FLAG'=>true,'FOLDER'=>true,'TRASH'=>true,'JUNK'=>true,'DIRECTORYID'=>true) 
					);
				break;
			case 'mini_publication':
				$this->info_profile = 
					new InfoProfile ( 
						array('MEDIATYPE'=>true,'TEMPLATE'=>true,'PAGETOCALL'=>true) 
					);
				$this->get_descriptions=true;
				$this->desc_profile=new DescriptionProfile('label');
				break;
			default:
				$this->info_profile = 
					new InfoProfile();
		}
		if($GLOBALS["php_request"]){
			$this->desc_profile->setAccessMode(NECTIL_PUBLIC);
		}else{
			$this->desc_profile->setAccessMode(NECTIL_OS);
		}
		if ($GLOBALS["php_request"] && isset($GLOBALS["NectilLanguage"]) && $GLOBALS['restrict_language']){
			$this->desc_profile->setLanguageMode(NECTIL_UNI_LNG);
			$this->desc_profile->setLanguage($GLOBALS["NectilLanguage"]);
		}else
			$this->desc_profile->setLanguageMode(NECTIL_MULTI_LNG);
			
		if(isset($GLOBALS["priority_language"]) && $GLOBALS["priority_language"]!==false){
			$this->desc_profile->setPriorLanguage($GLOBALS["priority_language"]);
		}
		return $skel_profile;
	}
	
	// resolves a profile described in a XML node
	function Sushee_ElementProfile($node){
		if(is_string($node)){ // the name of a profile 'complete','publication', etc
			$this->getPredefinedProfile($node);
		}else if(is_object($node)){
			
			if($node->nodename($profile_path)=='RETURN'){
				$this->isReturn = true;
			}
			// --- READ-ONLY ---
			$mode = $node->getData('/INFO[1]/@mode');
			if(!$mode)
				$mode = $node->getData('/@mode');
			if ( $node->valueOf('/@profile')){
				$profile_name = $node->getData('/@profile');

				$named_profile = $this->getPredefinedProfile($profile_name);
				if($mode)
					$this->mode = $mode;
				return $named_profile;
			}
			if(!$mode)
				$mode = 'normal';
			// --- INFO ---
			$get_info = $node->getData('/INFO[1]/@get');

			if($get_info==='false' ) $get_info=false;
			else{
				if($this->isReturn && !$node->exists('/INFO[1]'))
					$get_info=false;
				else
					$get_info=true;
			}
			// attribute on INFO allowing to get the infos of the contact with CREATORID indicated in element
			$get_creator = $node->getData('/INFO[1]/@creator_info');
			if(!$get_creator){
				$get_creator = $node->getData('/INFO[1]/@creator-info');
			}
			if(!$get_creator){
				$get_creator = $node->exists('/INFO[1]/CREATORID/INFO');
			}
			
			// attribute on INFO allowing to get the infos of the contact with MODIFIERID indicated in element
			$get_modifier = $node->getData('/INFO[1]/@modifier_info');
			if(!$get_modifier){
				$get_modifier = $node->getData('/INFO[1]/@modifier-info');
			}
			if(!$get_modifier){
				$get_modifier = $node->exists('/INFO[1]/MODIFIERID/INFO');
			}
		
			// attribute on INFO allowing to get the infos of the contact with OWNERID indicated in element
			$get_owner = $node->getData('/INFO[1]/@owner_info');
			if(!$get_owner){
				$node->getData('/INFO[1]/@owner-info');
			}
			if(!$get_owner){
				$get_owner = $node->exists('/INFO[1]/OWNERID/INFO');
			}
		
			// attribute on INFO allowing to get supplementary info about the dates
			$get_weekdays = $node->getData('/INFO[1]/@weekdays')==='true';
			$get_timestamp = $node->getData('/INFO[1]/@timestamp')==='true';
			$get_ymd = $node->getData('/INFO[1]/@year-month-day')==='true';

			if ($get_info){
				if($node->exists("/INFO[1]/*")){
					$profile_fields = $node->getElements("INFO/*[@get!='false' or not(@get)]");
					$profile_array = array();
					if ( sizeof($profile_fields)!=0 ){
						foreach($profile_fields as $fieldnode){
							$profile_array[$fieldnode->nodeName()]=true;
						}
					}
					$info_profile = new InfoProfile( $profile_array );
				}else{
					$info_profile = new InfoProfile( false );
				}
				$info_profile->includeWeekday($get_weekdays);
				$info_profile->includeTimestamp($get_timestamp);
				$info_profile->includeYearMonthDay($get_ymd);
				$info_profile->includeCreatorInfo($get_creator);
				$info_profile->includeModifierInfo($get_modifier);
				$info_profile->includeOwnerInfo($get_owner);
				$this->info_profile = $info_profile;
			}
			// --- DESCRIPTION ---
			$description_profile_path = $profile_path.'/DESCRIPTIONS[1]';

			$get_descriptions = $node->getData($description_profile_path.'/@get');
			$node_descriptions = $node->exists($description_profile_path);
			if(!$node_descriptions){
				$description_profile_path = $profile_path.'/DESCRIPTION[1]';
				$node_descriptions = $node->exists($description_profile_path);
			}else{
				if($node->exists($description_profile_path.'/DESCRIPTION[1]'))
					$description_profile_path = $description_profile_path.'/DESCRIPTION[1]';
			}

			if( ($get_descriptions==='true' || ($node_descriptions && $get_descriptions===FALSE))) $get_descriptions=true;
			else $get_descriptions=false;
			$desc_profile = new DescriptionProfile();
			if($get_descriptions){
				// this is for all depth : no way to get different description profile at different depth
				$desc_profile_name = $node->getData($description_profile_path.'/@profile');
				if($desc_profile_name)
					$desc_profile = new DescriptionProfile($desc_profile_name);
				else
					$desc_profile = new DescriptionProfile();
				/* CALLER WANT TO KNOW WHICH OTHER LANGUAGES ARE AVAILABLE */
				$desc_stats = $node->getData($description_profile_path.'/@stats');
				$desc_profile->setLanguageAvailability($desc_stats==='true');
			
				/* CALLER WANT TO KNOW the weekdays */
				$desc_weekdays = $node->getData($description_profile_path.'/@weekdays');
				$desc_profile->setWeekdaysAvailability($desc_weekdays==='true');
			
				$desc_status = $node->getData($description_profile_path.'/@status');
				if($desc_status)
					$desc_profile->setStatusMode($desc_status);
			
				if($GLOBALS["php_request"]){
					$desc_profile->setAccessMode(NECTIL_PUBLIC);
				}else{
					$desc_profile->setAccessMode(NECTIL_OS);
				}
			
				/* CALLER WANT TO DISCARD THE ELEMENTS WHICH DONT HAVE A DESCRIPTION */
				$desc_discarding = $node->getData($description_profile_path.'/@discard-element-if');

				/* LOOKING WHICH FIELDS ARE WANTED IN THE RETURNED XML */
				$node_profile = $node->getElements($description_profile_path.'/*');
				if($node_profile){
					$desc_profile->reset();
					foreach($node_profile as $node){
						$nodename_profile = $node->nodeName();
						if($nodename_profile!='CUSTOM'){
							$desc_profile->activateNativeField($nodename_profile);
						}else{
							$desc_profile->activateNativeField($nodename_profile);
							$custom_nodes = $node->getElements('./*');
							foreach($custom_nodes as $custom){
								$desc_profile->activateCustomField($custom->nodeName());
							}
						}
					
					}
				}
				/* WHICH LANGUAGES MUST BE RETURNED */
				$desc_language = $node->getData($description_profile_path.'/@languageID');
				if (!$desc_language)
					$desc_language = $node->getData($description_profile_path.'/LANGUAGEID');
				if (!$desc_language)
					$desc_language='';
				if ($GLOBALS["php_request"] && isset($GLOBALS["NectilLanguage"]) && $GLOBALS['restrict_language'] && $desc_language=='')
					$desc_language = $GLOBALS["NectilLanguage"];
				if ($desc_language==='all')
					$desc_language='';
			
				if($desc_language!=''){
					$desc_profile->setLanguageMode(NECTIL_UNI_LNG);
					$desc_profile->setLanguage($desc_language);
				}else{
					$desc_profile->setLanguageMode(NECTIL_MULTI_LNG);
				}
				$desc_output = $node->getData($description_profile_path.'/@output');
				if (!$desc_output)
					$desc_output = 'html';
				if(isset($GLOBALS["priority_language"]) && $GLOBALS["priority_language"]!==false){
					$desc_profile->setPriorLanguage($GLOBALS["priority_language"]);
				}
				$desc_profile->setDestination($desc_output);
			}
			// --- CATEGORIES ---
			$get_categories = $node->getData('/CATEGORIES[1]/@get');
			$node_categories = $node->exists('/CATEGORIES[1]');
			if( ($get_categories==='true'|| ($node_categories && $get_categories===FALSE))) $get_categories=true;
			else $get_categories=false;
			// --- COMMENTS ---
			$get_comments = $node->getData('/COMMENTS[1]/@get');
			$node_comments = $node->exists('/COMMENTS[1]');
			if( ($get_comments==='true' || ($node_comments && $get_comments===FALSE))) $get_comments=true;
			else $get_comments=false;
			// --- DEPENDENCIES ---
			$get_dependencies = $node->getData('/DEPENDENCIES[1]/@get');
			$node_dependencies = $node->exists('/DEPENDENCIES[1] | '.$profile_path.'/DEPENDENCY[1]');
			if( ($get_dependencies==='true' || ($node_dependencies && $get_dependencies===FALSE) )) $get_dependencies=true;
			else $get_dependencies=false;
			// --- FREELINKS ---
			$get_freelinks = $node->getData('/FREELINKS[1]/@get');
			$node_freelinks = $node->exists('/FREELINKS[1]');
			if( ($get_freelinks==='true' || ($node_freelinks && $get_freelinks===FALSE))) $get_freelinks=true;
			else $get_freelinks=false;
			if($get_freelinks){
				$moduleTarget = $node->getData('/FREELINKS[1]/@module');
				$moduleTargetID = FALSE;
				if ($moduleTarget){
					$moduleTargetInfo=moduleInfo($moduleTarget);
					if(!$moduleTargetInfo->loaded)
						$moduleTargetInfo=false;
				}
				$freeOnly = ($node->getData('/FREELINKS[1]/@freeOnly')==='true');

				if ($node->valueOf('/FREELINKS[1]/@profile') ){
					$freelink_profile = array('profile_name'=>$node->getData('/FREELINKS[1]/@profile'));
				}else if($node->exists('/FREELINKS[1]/WITH[1]')){
					$freelink_profile = array('profile_xml'=>$profile_xml,'profile_path'=>$profile_path.'/FREELINKS[1]/WITH[1]');
				}else{
					$freelink_profile = array('profile_name'=>'mini');
				}
				$freelinks_config = array('freeOnly'=>$freeOnly,'module'=>$moduleTargetInfo,'profile'=>$freelink_profile);


			}
			// --- PROPERTIES ---
			$get_properties = $node->getData('/PROPERTIES[1]/@get');
			$node_properties = $node->exists('/PROPERTIES[1]');
			if( ($get_properties==='true' || ($node_properties && $get_properties===FALSE))) $get_properties=true;
			else $get_properties=false;

			$get_omnilinks = $node->exists('/OMNILINKS[1]');
		}
		
		$this->mode= $mode;
		$this->get_owner= $get_owner;
		$this->get_modifier= $get_modifier;
		$this->get_creator= $get_creator;
		$this->get_weekdays= $get_weekdays;
		$this->freelinks_config= $freelinks_config;
		$this->get_info= $get_info;
		$this->desc_profile= $desc_profile;
		$this->desc_discarding= $desc_discarding;
		$this->profileFields_by_module= $profileFields_by_module;
		$this->get_dependencies= $get_dependencies;
		$this->get_descriptions= $get_descriptions;
		$this->get_categories= $get_categories;
		$this->get_freelinks= $get_freelinks;
		$this->get_comments= $get_comments;
		$this->get_properties= $get_properties;
		$this->get_omnilinks= $get_omnilinks;
		$this->path= $profile_path;
		$this->xml= $profile_xml;
		
	}
	
	function returnInfo(){
		return $this->get_info;
	}
	
	function getInfoMode(){
		return $this->mode;
	}
	
	function getIncludedFields(){
		if($this->info_profile){
			return $this->info_profile->getIncludedFields();
		}
		return array();
	}
	
	function getInfoProfile(){
		return $this->info_profile;
	}
	
	function returnDescriptions(){
		return $this->get_descriptions;
	}
	
	function returnCategories(){
		return $this->get_categories;
	}
	
	function returnComments(){
		return $this->get_comments;
	}
	
	function returnProperties(){
		return $this->get_properties;
	}
	
	function returnFreelinks(){
		return $this->get_freelinks;
	}
	
	function returnOmnilinks(){
		return $this->get_omnilinks;
	}
}

/*
object describing a sushee element ready to output
*/
class Sushee_SearchOutputElement extends SusheeObject{
	
	var $module;
	var $ID;
	var $depth;
	var $security;
	var $attributes;
	var $row;
	var $info_xml;
	var $IsPrivate;
	var $type;
	var $profileNode;
	var $cycle;
	var $more;
	var $dependencies;
	
	function getUniqueID(){
		return $this->module.'_'.$this->ID;
	}
	
	function getID(){
		return $this->ID;
	}
	
	function getRow(){
		return $this->row;
	}
	
	function getProfileNode(){
		return $this->profileNode;
	}
	
}

/*
object describing a set of elements for which we want the dependencies of a certain deptype
*/
class Sushee_SearchOutputDependenciesSet extends SusheeObject{
	
	var $depTypeID;
	var $elemIDs = array();
	var $profileNode;
	
	function Sushee_SearchOutputDependenciesSet($depType){
		$this->depTypeID = $depType->getID();
	}
	
	function getDepType(){
		return depType($this->depTypeID);
	}
	
	function setProfileNode($profileNode){
		$this->profileNode = $profileNode;
	}
	
	function getProfileNode(){
		return $this->profileNode;
	}
	
	function getElementIDs(){
		return $this->elemIDs;
	}
}

/*
object selecting which profile (for the DESCRIPTION) should be used for an element
*/
class sushee_DescriptionProfileManager extends SusheeObject{
	
	function sushee_DescriptionProfileManager(){
		$this->profileFactory = new Sushee_ElementProfileFactory();
		$this->profiles = new Vector();
	}
	
	function setProfile($key,$profile){
		$this->profiles->add($key,$profile);
	}
	
	function getProfile($element){
		return $this->profileFactory->getProfile($element->getProfileNode())->desc_profile;
	}
	
	function getLanguageMode(){
		$this->profiles->reset();
		$lgMode = NECTIL_UNI_LNG;
		while($profile = $this->profiles->next()){
			if($profile->getLanguageMode()==NECTIL_MULTI_LNG)
				$lgMode = NECTIL_MULTI_LNG;
		}
		return $lgMode;
	}
	
	function getAccessMode(){
		$this->profiles->reset();
		$accessMode = NECTIL_PUBLIC;
		while($profile = $this->profiles->next()){
			if($profile->getAccessMode()==NECTIL_OS)
				$accessMode = NECTIL_OS;
		}
		return $accessMode;
	}
	
	function getStatusList(){
		$this->profiles->reset();
		$statusList = array();
		while($profile = $this->profiles->next()){
			$statusList = array_merge($statusList,$profile->getStatusList());
		}
		return $statusList;
	}
	
	function getLanguage(){
		$this->profiles->reset();
		$profile = $this->profiles->next();
		return $profile->getLanguage();
	}
	
	function getLanguageAvailability(){
		$this->profiles->reset();
		$avail = false;
		while($profile = $this->profiles->next()){
			if($profile->getLanguageAvailability()==true)
				$avail = true;
		}
		return $avail;
	}
	
}
/*
object managing the xsushee output having a SQL result set and a profile described by a XML node
*/
class Sushee_SearchOutputManager extends SusheeObject{
	
	var $moduleID;
	var $depth;
	var $main_rs;
	var $files_collect = false;
	var $used_files;
	var $profile_config;
	
	var $operationNode = false; // at the moment only used in search.inc.php, and only useful for postprocessing
	
	function Sushee_SearchOutputManager(){
		$this->depth = false;
	}
	
	// operation node is the node containing the profile node (RETURN or WITH)
	function setOperationnode($node){
		$this->operationNode = $node;
	}
	
	function getOperationnode(){
		return $this->operationNode;
	}
	
	// for compatibility, we kept this strange config array that can contain a profile node or a profile name
	function setProfileConfig($profile_config){
		$this->profile_config = $profile_config;
	}
	
	// allows to collect every file contained in the elements returned in the output, to have an archive with th datas and the files used
	function setFilesCollect($bool){
		$this->files_collect = $bool;
		if($bool && !is_array($this->used_files))
			$this->used_files = array();
	}
	
	// returns the files used in the elements present in the output
	function getFiles(){
		return $this->used_files;
	}
	
	// the result set from which we are going to produce the xsushee output
	function setResultSet(/* SQL ResultSet */$rs){
		$this->main_rs = $rs;
	}
	
	// the depth is how many levels of elements the user wants to have in his output
	function setDepth($depth){
		$this->depth = $depth;
	}
	
	// module (object type) of the elements returned in the first level
	function setModule($moduleID){
		if(is_numeric($moduleID))
			$this->moduleID = $moduleID;
		if(is_object($moduleID))
			$this->moduleID = $moduleID->getID();
	}
	
	function getModule(){
		return moduleInfo($this->moduleID);
	}
	
	// element obj is an object containing the different parts of the output of an element
	function getElementObj($moduleInfo,$elem,$profileNode){
		$ID = $elem['ID'];
		$completeID = $moduleInfo->getName().'_'.$ID;
		$elt_obj = new Sushee_SearchOutputElement();
		
		$elt_obj->ID = $ID;
		
		if ($elem['DependencyTypeID']!=0){
			$dependencyType = depType($elem['DependencyTypeID']);
			if ($dependencyType->loaded)
				$attributes.= ' linkType="'.$dependencyType->name.'"';
		}
		
		if($moduleInfo->getName()=='mail' && $elem['html']==1)
			$attributes.=" html='true'";
		$elt_obj->attributes = $attributes;
		$moduleName = strtoupper($moduleInfo->getName());
		$elt_obj->module = $moduleName;
		$elt_obj->depth = 0;
		
		// saving the security on the element to display it in the XML
		if(Sushee_Request::isSecured()){
			// private by default
			$security = '0';
			// writable element
			if($moduleInfo->isElementAuthorized($elem,'W')){
				$security = 'W';
			// readonly element
			}else if($moduleInfo->isElementAuthorized($elem,'R')){
				$security = 'R';
			}
			$elt_obj->security = $security;
		}
		
		$elt_obj->row = $elem;
		$elt_obj->profileNode = $profileNode;
		return $elt_obj;
	}
	
	// returns the complete output XML
	function getXML(){
		if (is_string($this->main_rs) || !$this->main_rs )
			return '';
		if (is_object($this->main_rs) && $this->main_rs->RecordCount()==0)
			return '';
		
		if($this->profile_config){
			if($this->profile_config['profile_name']){
				$xml = new XML('<RETURN profile="'.$this->profile_config['profile_name'].'"/>');
				$profileNode = $xml->getElement('/RETURN');
			}else{
				$profileNode = new XMLNode($this->profile_config['profile_xml'],$this->profile_config['profile_path']);
			}
		}else if($this->getOperationnode()){
			$profileNode = $this->getOperationnode()->getElement('/RETURN');
			if(!$profileNode){
				$profileNode = $this->getOperationnode()->getElement('/*/WITH');
			}
		}
		if(!$profileNode){
			// fake empty profileNode
			$xml = new XML('<RETURN/>');
			$profileNode = $xml->getElement('/RETURN');
			
			// compatibility with the Flash where requesting with no profile node (no RETURN) was giving INFO anyway
			$request = new Sushee_Request();
			if($request->isOsRequest()){
				$profileNode->appendChild('<INFO/>');
			}
		}
		
		$this->depth = $profileNode->getAttribute('depth');
		if(!$this->depth){
			$this->depth = 1 + $profileNode->count('//DEPENDENCIES');
		}

		
		$db_conn = db_connect();
		$main_rs = $this->main_rs;
		$moduleInfo = moduleInfo($this->moduleID);
		if (is_array($main_rs))
			$elem = $main_rs;
		else
			$elem = $main_rs->FetchRow();
		$moduleName = strtoupper($moduleInfo->name);
		$index = 0;
		
		// pushing root elements (first levek) into an array to handle them
		$root_elements = array();
		$to_handle = array();
		$previous_level_elements = array();
		while($elem){
			$elt_obj = $this->getElementObj($moduleInfo,$elem,$profileNode);
			
			if ($main_rs->result_page){
				$this_index = $main_rs->startIndex+$index+1;
				$elt_obj->attributes.=" onTotalCount='$this_index'";
			}
			
			$to_handle[] = $elt_obj;
			$root_elements[] = $elt_obj;
			if (is_array($main_rs))
				$elem = FALSE;
			else
				$elem = $main_rs->FetchRow();
			$index++;
		}
		
		// treating each element, and managing its children if necessary (and pushing them into the handle array)
		$next_level = array();
		$this->profileFactory = new Sushee_ElementProfileFactory();
		// new version of the sushee description profile manager
		$descriptionProfileManager = new sushee_DescriptionProfileManager();
		while($elt_obj = array_shift($to_handle)){
			//debug_log('handling '.$elt_obj->module.' '.$elt_obj->ID.' at depth '.$elt_obj->depth);
			
			$moduleInfo = moduleInfo($elt_obj->module);
			
			// building the profile
			$profile = $this->profileFactory->getProfile($elt_obj->getProfileNode());
			$descriptionProfileManager->setProfile($elt_obj->getProfileNode()->getUniqueID(),$profile->desc_profile);
			
			// handling services
			if($profile->returnInfo()){
				$elt_obj->info_xml = $this->generateInfoXML($moduleInfo,$elt_obj->getRow(),$profile);
			}
			$moduleID = $moduleInfo->getID();
			$ID = $elt_obj->getID();
			$elem = $elt_obj->getRow();
			if ($profile->returnDescriptions() && $moduleInfo->getServiceSecurity('description',$elem)!=='0'){
				if(!isset($elements_wdesc_by_module[$moduleID][$ID])){ // dont replace if already existing
					$elements_wdesc_by_module[$moduleID][$ID] = $elt_obj;
				}
			}
			if ($profile->returnCategories() && $moduleInfo->getServiceSecurity('category',$elem)!=='0'){
				if(!isset($elements_wcateg_by_module[$moduleID][$ID])){ // dont replace if already existing
					$elements_wcateg_by_module[$moduleID][$ID] = $elt_obj;
				}
			}
			if ($profile->returnComments() && $moduleInfo->getServiceSecurity('comment',$elem)!=='0'){
				if(!isset($elements_wcomments_by_module[$moduleID][$ID])){ // dont replace if already existing
					$elements_wcomments_by_module[$moduleID][$ID] = $elt_obj;
				}
			}
			if ($profile->returnProperties() && $moduleInfo->getServiceSecurity('property',$elem)!=='0'){
				if(!isset($elements_wproperties_by_module[$moduleID][$ID])){ // dont replace if already existing
					$elements_wproperties_by_module[$moduleID][$ID] = $elt_obj;
				}
			}
			if ($profile->returnFreelinks() && $moduleInfo->getServiceSecurity('freelink',$elem)!=='0'){
				$elt_obj->freelinks_xml = $this->handleFreelinks($moduleInfo,$ID,$profile->freelinks_config);
			}
			if ($profile->returnOmnilinks() && $moduleInfo->getServiceSecurity('omnilink',$elem)!=='0'){
				$elt_obj->omnilinks_xml = $this->handleOmnilinks($moduleInfo,$ID,$profile);
			}
			
			//handling dependencies of element if not yet at maximum depth
			if($this->depth == 'all' || $elt_obj->depth + 1 < $this->depth){
				// keeping elements in one array in order to attach them their dependencies once we got them
				$previous_level_elements[$elt_obj->getUniqueID()] = $elt_obj;
				
				$depTypeNodes = $elt_obj->profileNode->getElements('DEPENDENCIES/DEPENDENCY[@type]');
				if(sizeof($depTypeNodes)){
					$depTypeSet = new Vector();
					foreach($depTypeNodes as $typeNode){
						$dependencyType = &new dependencyType($typeNode->getAttribute('type'));
						$depTypeSet->add($dependencyType->getID(),$dependencyType);
					}
				}else{
					if($elt_obj->depth <= $this->depth  || $this->depth=='all'){
						$depTypeSet = new DependencyTypeSet($moduleInfo->getID());
					}else{
						$depTypeSet = false;
					}
				}
				if($depTypeSet){
					while($dependencyType = &$depTypeSet->next()){
						$elt_obj->dependencies[$dependencyType->getID()] = array();
						
						// determining where to look for profile and saving it
						$profileNode = $elt_obj->profileNode;
						$depType_profileNode = $elt_obj->profileNode->getElement('DEPENDENCIES/DEPENDENCY[@type="'.$dependencyType->getName().'"]');
						if($depType_profileNode){
							$profileNode = $depType_profileNode;
						}
						$deps_profileNode = $elt_obj->profileNode->getElement('DEPENDENCIES[* and not(DEPENDENCY)]');
						if($deps_profileNode){
							$profileNode = $deps_profileNode;
						}
						
						// all elements with a same deptype to explore are kept together and we make the request later once for all elements
						$depSetAssembler = $next_level[$dependencyType->getID()];
						if(!$depSetAssembler){
							// it does not exist yet
							$depSetAssembler = new Sushee_SearchOutputDependenciesSet($dependencyType);
							$depSetAssembler->setProfileNode($profileNode);
							
							$next_level[$dependencyType->getID()] = $depSetAssembler;
						}
						$depSetAssembler->elemIDs[] = $elt_obj->getID();
						
					}
				}
			}
			$return_values = array();
			$process = $moduleInfo->postProcess('SEARCH',$ID,$this->getOperationnode(),$elem,$elem,$return_values /* fake array because, return values is not used */);
			
			$elt_obj->postprocess = $process->getResponse();
			
			// we finished a level, looking what is to examine next
			// this is more optimal to do one sql request to get all elements for a specific deptype in one request
			if(sizeof($to_handle)==0){
				while($depSet = array_shift($next_level)){
					$dependencyType = $depSet->getDepType();
					$profileNode = $depSet->getProfileNode();
					$moduleOriginInfo = $dependencyType->getModuleOrigin();
					$moduleTargetInfo = $dependencyType->getModuleTarget();
					
					// SQL for getting the dependencies
					$origin_cond='(dep.`'.$dependencyType->getOriginFieldname().'` IN ('.implode(',',$depSet->getElementIDs()).'))';
					
					$returned_str = '';
					$returned_info = $profileNode->getElements('/INFO/*');
					$which_element = 'element';
					if(sizeof($returned_info)>0){
						foreach ($returned_info as $info_node){
							$fieldname = $moduleTargetInfo->getFieldName($info_node->nodeName());
							if($fieldname && $fieldname != 'ID'){ // if fieldname exists, and ID is added automatically
								$returned_str .= $which_element.'.`'.$fieldname.'`,';
							}
						}
						$returned_str .= $which_element.'.`ID`';
					}else{
						$returned_str .= $which_element.'.*';
					}
					
					
					$sql = "SELECT DISTINCT ".$returned_str.",dep.`Comment` AS DepComment,dep.`DepInfo`,dep.`".$dependencyType->getOriginFieldname()."` FROM `".$moduleTargetInfo->tableName."` AS element,`".$dependencyType->getTablename()."` AS dep WHERE $origin_cond AND  dep.`DependencyTypeID`='".$dependencyType->getIDInDatabase()."' AND element.`ID` = dep.`".$dependencyType->getTargetFieldname()."` AND element.`Activity`=1";

					if ($GLOBALS["php_request"] && $moduleTargetInfo->getName()=='media' && !($GLOBALS["take_unpublished"]===true)){
						$sql.=' AND element.`Published` = 1 ';
					}
					$sql.=" ORDER BY dep.`".$dependencyType->getOriginFieldname()."`,dep.`DependencyTypeID`,dep.`".$dependencyType->getOrderingFieldname()."` ASC";
					sql_log($sql);
					$dep_rs = $db_conn->Execute($sql);
					
					if($dep_rs){
						while($dep_row = $dep_rs->fetchRow()){
							$origin_completeID = $moduleOriginInfo->getxSusheeName().'_'.$dep_row[$dependencyType->getOriginFieldname()];
							
							$elt_obj = $previous_level_elements[$origin_completeID];
							
							$dep_elt_obj = $this->getElementObj($moduleTargetInfo,$dep_row,$profileNode);
							$dep_elt_obj->depth = $elt_obj->depth + 1;
							$to_handle[] = $dep_elt_obj;
							$more='<DEPINFO>'.$dep_row['DepInfo'].'</DEPINFO>';
							$more.='<COMMENT>'.$dep_row['DepComment'].'</COMMENT>'; // DepComment is not the real name of the field, but it was aliased like that in the SQL request in order to avoid confusion with any Comment field in the element
							// check we are not in private mode
							$dep_elt_obj->type = 'dep';
							$dep_elt_obj->IsPrivate = $this->getPrivacy($moduleTargetInfo,$dep_row);
							$dep_elt_obj->cycle = false;
							$dep_elt_obj->more = $more;
							$elt_obj->dependencies[$dependencyType->getID()][] = $dep_elt_obj;
						}
					}
				}
				$next_level = array();
				$previous_level_elements = array();
			}
			$GLOBALS["TotalNectilElements"]++;
		}
		
		
		foreach($elements_wdesc_by_module as $moduleID=>$elements){
			$descManager = new descriptionsOutputManager($moduleID,$elements);
			$descManager->setProfileManager($descriptionProfileManager);
			$descriptionSetVector = &$descManager->getDescriptionSets();
			$descriptionSetVector->reset();
			while($descSet = &$descriptionSetVector->next()){
				$xml = $descSet->getXML();
				$elements_wdesc_by_module[$moduleID][$descSet->elementID]->descriptions_xml.= $xml;
			}
			if($this->files_collect===true){
				$this->used_files=array_merge($this->used_files,$descManager->getFiles());
			}
				
		}
		
		foreach($elements_wcateg_by_module as $moduleID=>$elements){
			$moduleInfo = moduleInfo($moduleID);
			$rs = getCategories($moduleID,$elements);
			if (is_object($rs)){
				while($service = $rs->FetchRow()){
					$serviceElemID = $service['TargetID'];
					$elements_wcateg_by_module[$moduleID][$serviceElemID]->categories_xml.=generateCategoriesXML($service);
				}
			}
		}
		foreach($elements_wcomments_by_module as $moduleID=>$elements){
			$moduleInfo = moduleInfo($moduleID);
			$rs = getComments($moduleInfo->ID,$elements);
			if (is_object($rs)){
				while($service = $rs->FetchRow()){
					$serviceElemID = $service['TargetID'];
					$elements_wcomments_by_module[$moduleID][$serviceElemID]->comments_xml.=generateCommentsXML($service,$desc_output);
				}
			}
		}
		foreach($elements_wproperties_by_module as $moduleID=>$elements){
			$moduleInfo = moduleInfo($moduleID);
			$rs = getProperties($moduleInfo->ID,$elements);
			if (is_object($rs)){
				while($service = $rs->FetchRow()){
					$serviceElemID = $service['TargetID'];
					$elements_wproperties_by_module[$moduleID][$serviceElemID]->properties_xml.=generatePropertyXML($service);
				}
			}
		}
		
		foreach($root_elements as $elt_obj){
			$query_result.=$this->generateElementXML($depth,0,$elt_obj,$isGet);
		}
		return $query_result;
	}
	
	// returns the privacy of a single element (a private element is an element that user cannot see because he is NOT one of the owners)
	function getPrivacy($moduleInfo,$elem){
		// check we are not in private mode
		$privacy = false;
		if($moduleInfo->IsPrivacySensitive){
			if($moduleInfo->isElementAuthorized($elem)){
				$privacy = false;
			}else
				$privacy = true;
		}
		// check we are not limited to a subset of this module (virtual module)
		if($moduleInfo->composite===true){
			if($moduleInfo->getActionSecurity('SEARCH',$elem)===false){
				$privacy = true;
			}
		}
		// if it's the user's own contact, we can show it
		if( $moduleInfo->name=='contact' && $elem['ID']==OfficityUser::getID()){
			$privacy = false;
		}
		return $privacy;
	}
	
	// returns the output in the INFO node
	function generateInfoXML($moduleInfo,$elem,$profile){
		$fields_array=$moduleInfo->getFieldsBySecurity('R');
		//$this_profile = $profile['profileFields_by_module'][$moduleInfo->ID];
		if (is_object($profile)){
			$profile_array = $profile->getIncludedFields();
		}else{
			$profile_array = false;
		}
		// his own contact fiche
		if($moduleInfo->name=='contact' && $elem['ID']===OfficityUser::getID()){
			$normal_fields_array = $fields_array;
			$personal_fields_array = $moduleInfo->getFieldsBySecurity('0');

			if(!isset($normal_profile_array['ADMINNOTES'])){
				unset($fields_array['ADMINNOTES']);
			}
			if($profile->getInfoMode()=='read-only'){
				return $this->generateInfoXMLReadOnly($moduleInfo,$elem,$personal_fields_array,$profile_array,$profile->desc_output);
			}else{
				$infoGenerator = new NectilElementInfo($moduleInfo->getID(),$elem['ID'],$elem);
				if(is_object($this_profile)){
					$infoGenerator->setProfile($profile->getInfoProfile());
				}
				$infoGenerator->setSecurityProfile($personal_fields_array);
				return $infoGenerator->getXML();
			}	
		}else{
			if($profile->getInfoMode()=='read-only'){
				return $this->generateInfoXMLReadOnly($moduleInfo,$elem,$fields_array,$profile_array,$profile->desc_output);
			}else{
				$infoGenerator = new NectilElementInfo($moduleInfo->getID(),$elem['ID'],$elem);
				if(is_object($profile)){
					$infoGenerator->setProfile($profile->getInfoProfile());
				}
				$infoGenerator->setSecurityProfile($fields_array);
				return $infoGenerator->getXML();
			}
		}
	}
	
	
	// returns the XML for the INFO node, but in the special read-only mode, more compact (fields are written in attributes instead of node)
	function generateInfoXMLReadOnly(&$moduleInfo,&$elem,&$fields_array,$profile_array){
		$str='<INFO ';
		if ($profile_array===FALSE || $profile_array===NULL){
			$fields_nbr = count($fields_array);

			for($i=0;$i<$fields_nbr;$i++){
				$n=$fields_array[$i];
				$value=$elem[$n];
				$value = str_replace(array("\r\n", "\r", "\n"), '', $value);
				if (!$moduleInfo->isXMLField($fields_array[$i])){
					$str.=strtoupper($n).'="'.encode_to_XML($value).'" ';
				}
			}
		}else{
			$fields_nbr = count($fields_array);
			$profile_nbr = count($profile_array);
			$fields_ok = 0;
			for($i=0;$i<$fields_nbr;$i++){
				$n=$fields_array[$i];
				$value=$elem[$n];
				$value = str_replace(array("\r\n", "\r", "\n"), '', $value);
				//$n=strtoupper($n);
				$asked = FALSE;
				if (isset($profile_array[strtoupper($n)]))
					$asked = TRUE;
				if ($asked){
					if (!$moduleInfo->isXMLField($fields_array[$i])){
						$str.=strtoupper($n).'="'.encode_to_XML($value).'" ';
					}
				}
			}
		}
		$str.='/>';
		return $str;
	}
	
	// builds the complete output for an element, using the different XML parts
	function generateElementXML($depth,$this_depth,&$element_obj,$isGet=false){
		$profile = $this->profileFactory->getProfile($element_obj->getProfileNode());
		
		$element_str='';
		$discard = false;
		if ($element_obj->cycle===true)
			$more_attributes='cycle="true" ';
		
		if($element_obj->IsPrivate===true)
			$more_attributes.='private="true" ';

		$element_str.='<'.$element_obj->module.' depth="'.($this_depth+1).'" '.$more_attributes.'ID="'.$element_obj->ID.'"'.$element_obj->attributes;
		
		if(Sushee_Request::isSecured()){
			$element_str.=' security="'.$element_obj->security.'"';
		}
		$element_str.='>';
		if ($element_obj->cycle!==true and $element_obj->IsPrivate!==true){
			if($depth==='all')
				$profile = $profile_at_depth['all'];
			$element_str.=$element_obj->info_xml;

			if($profile->returnDescriptions() ){
				if($profile->desc_discarding==='absent' && $element_obj->descriptions_xml==''){
					return '';
				}
				$element_str.='<DESCRIPTIONS>';
				$element_str.=$element_obj->descriptions_xml;
				$element_str.='</DESCRIPTIONS>';
			}
			if($profile->returnCategories() ){
				$element_str.='<CATEGORIES>';
				$element_str.=$element_obj->categories_xml;
				$element_str.='</CATEGORIES>';
			}
			if($profile->returnComments() ){
				$element_str.='<COMMENTS>';
				$element_str.=$element_obj->comments_xml;
				$element_str.='</COMMENTS>';
			}
			if($profile->returnProperties() ){
				$element_str.='<PROPERTIES>';
				$element_str.=$element_obj->properties_xml;
				$element_str.='</PROPERTIES>';
			}
			
			if(is_array($element_obj->dependencies)){
				$element_str.='<DEPENDENCIES>';
				foreach($element_obj->dependencies as $depID=>$deps){
					$dependencyType = depType($depID);
					$moduleTargetInfo = moduleInfo($dependencyType->ModuleTargetID);
					
					$element_str.='<DEPENDENCY type="'.$dependencyType->name.'" module="'.$moduleTargetInfo->name.'"  hits="'.sizeof($deps).'">';
					//debug_log('before deps '.$depID.' foreach '.sizeof($deps));
					foreach($deps as $dep){
						$element_str.=$this->generateElementXML($depth,$this_depth+1,$dep);
					}
					$element_str.='</DEPENDENCY>';
				}
				$element_str.='</DEPENDENCIES>';
			}
			if($profile->returnFreelinks())
				$element_str.=$element_obj->freelinks_xml;
				
			if($profile->returnOmnilinks())
				$element_str.=$element_obj->omnilinks_xml;
				
			$element_str.=$element_obj->more;
			
			if($element_obj->postprocess){
				$element_str.=$element_obj->postprocess;
			}
			
		}
		$element_str.='</'.$element_obj->module.'>';

		return $element_str;
	}
	
	// builds the output for the freelinks of an element
	// freelinks are DEPRECATED, they show to which objects the elements is linked
	function handleFreelinks(&$moduleInfo,$elemID,$freelinks_config = array()){
		$moduleTarget = $freelinks_config->module;
		$modules_array = array();
		if ($moduleTarget){
			$modules_array[]=$moduleTarget;
		}else{
			$modules = new modules();
			$modules_array = $modules->list;
		}
		$links_str='';

		foreach($modules_array as $moduleTargetInfo){
			$depTypes = new DependencyTypeSet($moduleTargetInfo->ID,$moduleInfo->ID);
			while($depType = $depTypes->next()){
				$rs = $this->getFreelinkTargets($moduleInfo,$elemID,$moduleTargetInfo,$depType->getID());
				if($rs){
					$manager = new Sushee_SearchOutputManager();
					$manager->setModule($moduleTargetInfo->ID);
					$manager->setResultSet($rs);

					$manager->setProfileConfig($freelinks_config['profile']);

					$links_str.=$manager->getXML();
				}
			}
			
		}
		 return "<FREELINKS>$links_str</FREELINKS>";
	}
	
	// returns the elements linked to a given object, with a specific deptype
	function getFreelinkTargets($moduleOriginInfo,$originID,$moduleTargetInfo,$dependencyTypeID){
		$db_conn = db_connect();
		$ModuleOriginID = $moduleOriginInfo->ID;
		$ModuleTargetID = $moduleTargetInfo->ID;
		$depType = depType($dependencyTypeID);
		
		$origin_cond = 'dep.`'.$depType->getTargetFieldname().'`='.$originID;
		
		$sql = "SELECT DISTINCT element.*,dep.`DependencyTypeID`,dep.`".$depType->getOriginFieldname()."` FROM `".$moduleTargetInfo->tableName."` AS element,dependencies AS dep WHERE $origin_cond AND element.ID=dep.`".$depType->getOriginFieldname()."` AND element.Activity=1";
		$sql.=" AND dep.`dependencyTypeID`=".$depType->getIDinDatabase();
		
		
		if ($GLOBALS["php_request"] && $moduleTargetInfo->name=='media' && !($GLOBALS["take_unpublished"]===true))
			$sql.=' AND element.`Published`=1 ';
		$sql.=' LIMIT 0,50'; // because freelinks can be outrageously numerous
		sql_log($sql);
		$rs = $db_conn->Execute($sql);
		return $rs;
	}
	
	// builds the output for the omnilinks of an element
	// omnilinks are links that are not restrained to a certain type of object
	function handleOmnilinks($moduleInfo,$elemID,$profile){
		// taking the different types of omnilink for this module
		$types = new sushee_omnilinkTypeSet(/*$moduleInfo->getID()*/);
		
		$links_str = '';
		
		
		$profile_node = new XMLNode($profile['xml'],$profile['path']);
		
		// user asked for specific types
		if($profile_node->exists('OMNILINKS/OMNILINK')){
			$types_nodes = $profile_node->getElements('OMNILINKS/OMNILINK');
			$types = new Vector();
			foreach($types_nodes as $type_node){
				$type = new sushee_OmnilinkType($type_node->getAttribute('type'));
				if($type->loaded){
					$types->add($type->getName(),$type);
				}
			}
		}
		
		$links_str.='<OMNILINKS>';
		// looping through the different types
		while($type = $types->next()){
			$hits = 0;
			$omnilink_profile_node = $profile_node->getElement('OMNILINKS');
			if($profile_node->getElement('OMNILINKS/OMNILINK[@type="'.$type->getName().'"]')){
				$omnilink_profile_node = $profile_node->getElement('OMNILINKS/OMNILINK[@type="'.$type->getName().'"]');
			}
			$elements_str = '';
			// taking all links with this type
			// first from the element to the multimodule 
			$elt_omnilinks = new sushee_ElementOmnilinkers($type,$moduleInfo,$elemID);
			while($omnilink = $elt_omnilinks->next()){
				$element = $this->handleOmnilink($type,$omnilink_profile_node,$type->getModule(),$omnilink->getOmnilinkerID());
				$elements_str.= $element;
				if($element)
					$hits++;
			}
			
			// now from the element to the omnilinker (of one specific type)
			$elt_omnilinks = new sushee_ElementOmnilinked($type,$elemID);
			while($omnilink = $elt_omnilinks->next()){
				$element=$this->handleOmnilink($type,$omnilink_profile_node,$omnilink->getModuleTarget(),$omnilink->getElementID());
				$elements_str.= $element;
				if($element)
					$hits++;
			}
			
			$links_str.='<OMNILINK type="'.$type->getName().'" hits="'.$hits.'">';
			$links_str.=$elements_str;
			$links_str.='</OMNILINK>';
		}
		$links_str.='</OMNILINKS>';
		
		return $links_str;
	}
	
	// builds the output for one omnilink to a given element
	function handleOmnilink($type,$profile_node,$moduleInfo,$elementID){
		
		$output_manager = new Sushee_SearchOutputManager();
		$output_manager->setDepth(false);
		
		// composing a  xSushee request taking the target element
		$target_requestXML = new XML(
			'<GET name="omnilinked">
				<'.$moduleInfo->getxSusheeName().' ID="'.$elementID.'"/>
				<RETURN>'.$profile_node->copyOf('/*').'</RETURN>
			</GET>');
		$profile_path = '/GET/RETURN';
		
		// SQL request taking the target element
		$sql='';
		$rs = getResultSet($moduleInfo,$target_requestXML,'/*[1]',$sql);
		
		// asking an output manager to compose a xSushee response corresponding to the request
		$output_manager->setResultSet($rs);
		$output_manager->setOperationNode($target_requestXML->getFirstchild());
		$output_manager->setModule($moduleInfo->getID());
		$profile = array('profile_xml'=>$target_requestXML,'profile_path'=>$profile_path);
		$output_manager->setProfileConfig($profile);
		
		return $output_manager->getXML();
	}
}

?>