<PUBLIC:COMPONENT tagname="LOCATIONSELECTOR">
	<@component name="LocationSelector">
		A Generic location selector for Visual Composer resources
	   <copyright>(c) SAP AG 2003-2009. All rights reserved.</copyright>
	</component@>
	
	<PUBLIC:PROPERTY name="LowerBoundFlavor" put="setLowerBoundFlavor"/>
	<PUBLIC:PROPERTY name="UpperBoundFlavor" put="setUpperBoundFlavor"/>
	<PUBLIC:PROPERTY name="indent" put="setIndent"/>
	<PUBLIC:PROPERTY name="showIcons" put="setShowIcons"/>
	<PUBLIC:PROPERTY name="TYPES" get="returnTYPES"/>
	<PUBLIC:PROPERTY name="REPOSITORY_DOMAIN" get="getREPOSITORY_DOMAIN"/>
	<PUBLIC:PROPERTY name="USING_USER_DATA" put="getUSING_USER_DATA"/>
	<PUBLIC:PROPERTY name="errMsg" get="getErrMessage"/>
	
	<PUBLIC:METHOD   name="setDisable"/>
	<PUBLIC:METHOD   name="initLocation"/>
	<PUBLIC:METHOD   name="getLocation"/>
	<PUBLIC:METHOD   name="saveUserData"/>
	<PUBLIC:METHOD   name="isSelectionValid"/>
	
	<PUBLIC:EVENT    name="onLocationChanged" ID="evtLocationChanged" />
	<PUBLIC:ATTACH   event="onresize" onevent="layout()" />
	
	<PUBLIC:DEFAULTS viewLinkContent="true"/>

	<HTML xmlns:stb="urn:guimachine-com:storyboard" xmlns:gml="urn:guimachine-com:gml">
		<HEAD>

			<META HTTP-EQUIV="MSThemeCompatible" CONTENT="no">
			
			#DEPENDENCIES[
				lib:Global.js
				lib:InputMgr.js
				lib~skin:styles.Input.css
			]
			
			#USING[dev:urn.UrnUtils.js]
			#USING[lib:Input.htc]
			#USING[lib:Button.htc]
			#USING[lib:Dialog.htc]
			
			#INCLUDE[lib:EventsMgr.js]
			#INCLUDE[lib:EnumMgr.js]
		
			<SCRIPT language="JavaScript">
			
				// PUBLIC enum for this HTC
				var TYPES = getTYPES();
				
				function returnTYPES(){
					return TYPES; 
				}
				
				var DIRECTION = {};
				DIRECTION.UP   = "UP";   
				DIRECTION.DOWN    = "DOWN";
				
				var errMsg = {};
				errMsg.Error = null;
				function getErrMessage(){
					return errMsg.Error;
				}
									
				var REPOSITORY_DOMAIN = {};
				REPOSITORY_DOMAIN.ALL            = "ALL";
				REPOSITORY_DOMAIN.LOCAL          = "LOCAL";
				REPOSITORY_DOMAIN.SOURCE_CONTROL = "SOURCE_CONTROL";
				function getREPOSITORY_DOMAIN(){
					return REPOSITORY_DOMAIN;
				}
				
				var USING_USER_DATA = {};
				USING_USER_DATA.YES = true;
				USING_USER_DATA.NO = false;
				function getUSING_USER_DATA(){
					return USING_USER_DATA;
				}
				
			
				/////////////////////////
				var _UDKEYS = getUserDataKeys();
				var _serverUserData = {}; // Reference to user data object
				var _location = null; // Selected location object
				var _flavor = null; // If falvor is NULL htc runs in MODEL flavor
				var _upperFlavor=null;
				var ch = $ENV.channel2;
				var _showIcons = false; // Indicates wether to show icons default ~false
				var __ENUMS = self.window.__ENUMS; // Make enum object single instance ! 
				var _DCObj = {};
				// The following 3 are clones of the domains which are used for the removeSelectUiNotification() function.
				var _RepEnumObj = null;
				var _ScEnumObj = null;
				var _DcEnumObj = null;
				
				var _qMode = null; //indicates whether to use the quick init function.
				var _usingUserData = true; //boolean which indicated whether to use the user data or not
				var _forcedRepository = REPOSITORY_DOMAIN.ALL; 
				var _disabledFields = null;
				var _isUserLocation = false; // ~TRUE when the user set the location (i.e. calling forceLocation function)
				var _allRepositories = null;

				/**
				this function triggeres the init() which initialize the location selector
				@param repDomain= Repository Domain holds the repository that the user (dialog) requests
				@param isUserData = bool which indicates if the user wishes to use the user data
				@param location = instance of a location to set - in cases the user knows the location a priori (from right-click for example)
				The only 2 ways a dialog can use/consume the location selector are using the bellow func as follows: 
				1. ls.initLocation(REPOSITORY_DOMAIN.<...>, ls.USING_USER_DATA.<...>);
				2. ls.initLocation(null,null,<location>);
				The first initializes the location selector using a forced repository or using the user data (if exists and matches the forced repository) without locking the fields.
				The second initializes the location selector with a specific location (right click) and locks the fields.
				*/
				function initLocation(repDomain, isUserData, location){
					if(!checkInput(repDomain, isUserData, location)){
						//in case of a wrong initialization we initializing using the default values
						repDomain = REPOSITORY_DOMAIN.ALL; 
						isUserData = false;
					}
					//if we have a valid location we use it for a quick init, EVEN if the other params are incorrect - that is to say checkInput function returned false
					if(location && ISA(location,'dev:Location')){
						quickInit(location);
						return;
					}
					var forcedLocation = null;
					_forcedRepository = repDomain;
					_usingUserData = isUserData;
					switch (_forcedRepository){
						case REPOSITORY_DOMAIN.LOCAL:
							if(_usingUserData && hasUserData(TYPES.REP)){
								//if the user data is pointing to local repository - same as the repository domain in this case
								if(verifyUserDataRepository()){
									init();	
								}
								//if the user data is pointing to source control repository
								else{
									forcedLocation = createForcedLocation();
									// make sure there are available repositories
									if(forcedLocation.getRepository())
										forceLocation(forcedLocation);
									#TRACE[2, "Mismatch in the Location Selector - Assuming there is no user data"];// the user data is pointing to source control repository while forcing a local repository
								}					
							}
							// using the user location with local location
							else{
								forcedLocation = createForcedLocation();
								// make sure there are available repositories
								if(forcedLocation.getRepository())
									forceLocation(forcedLocation);
							}
							break;
						case REPOSITORY_DOMAIN.SOURCE_CONTROL:
							if(_usingUserData && hasUserData(TYPES.REP)){
									forcedLocation = createForcedLocation();
									// make sure there are available repositories
									if(forcedLocation.getRepository())
										forceLocation(forcedLocation);
									#TRACE[2, "Mismatch in the Location Selector - Assuming there is no user data"];// the user data is pointing to local repository while forcing a source control repository						
							}
							else{
							// using the user location with source control location
								forcedLocation = createForcedLocation();
								// make sure there are available repositories
								if(forcedLocation.getRepository())
									forceLocation(forcedLocation);
							}
							break;
						case REPOSITORY_DOMAIN.ALL:
							init();	
							break;
						default:
							init();						
					}		
				}
				
				/**
				this function checks if the user data repository points to the same repository as the repository-domain sent by the user (by the dialog)
				*/
				function verifyUserDataRepository(){
					var allRep = filterRepositoryDomain(getAllRepositories());
					for(var index in allRep){
						if(_serverUserData[_UDKEYS[TYPES.REP]] == allRep[index].urn){
							return true;
						}
					}
					return false;
				}
				
				/**
				this function verifies that the parameters were sent correctly to the location selector initLocation function.
				The only 2 correct ways are: 
				1. ls.initLocation(REPOSITORY_DOMAIN.<...>, ls.USING_USER_DATA.<...>);
				2. ls.initLocation(null,null,<location>);
				*/
				function checkInput(repDomain, isUserData, location){
					if(location && ISA(location,'dev:Location')){
						if(null == repDomain && null == isUserData){ //input is valid
							return true;
						}
						else{
						//in this case we have a valid location. We write to the log but eventually we will initialize using the location that was sent. 
							#TRACE[4, "Wrong initialization of Location Selector, incorrect params. When sending a location to location selector Repository Domain and isUserData should be null. meaning: 'ls.initLocation(null,null,location)'"];
							return false;
						}
					}
					else
					//in this case we have no location and at least one of the other params is wrong. 
						if((repDomain!=REPOSITORY_DOMAIN.LOCAL && repDomain!=REPOSITORY_DOMAIN.SOURCE_CONTROL && repDomain!=REPOSITORY_DOMAIN.ALL) || (isUserData!=true && isUserData!=false)){
							#TRACE[4, "Wrong initialization of Location Selector, incorrect params. Either Repository Domain or bool isUserData is incorrect"];
							return false;
						}
					return true;
				}
				
				/**
				When forcing a location, updating memberes before moving on to init. 
				these memberes are used during the initialization in order to force this location.
				*/
				function forceLocation(location){
					_location = location;
					_isUserLocation = true;
					if(!_qMode){
						init();
					}
				}
				
				/**
				this function initializes the location selector using a predefind location (from right click for instance).
				unlike the init() function, it avoids calling the channel and it disables the fields
				@param disabledFields - use to determine which fields should be disables when process is done.
				*/
				function quickInit(location, disabledFields){
					_qMode = true;
					// if no repository is found
					if(!location.getRepository())
						return;
					forceLocation(location);
					if(!disabledFields){
						_disabledFields = TYPES.DC;
					}
					else{
						_disabledFields = disabledFields;
					}
					
					QIsetRepository();
					if (!needToContinue(TYPES.REP)){ 
						endInit();
						return;
					}
					QIsetSC();
					if (!needToContinue(TYPES.SC)){ 
						endInit();
						return;
					}
					QIsetDC();
				}
					
				/* QI - stands for Quick Init.
				 * This is an internal func used by the quickInit func in order to initialize the repository
				 */
				function QIsetRepository(){
					var res = [];
					res[0] = getRepositoryByUrn(_location.getRepository());
					if (!fldRep._dis) fldRep.enabled = true;
					var RepEnumObj = createEnumAndDefVal(res, TYPES.REP);
					if (!isValidEnumRes(RepEnumObj)){
						endInit();
						return;
					}
					fldRep.domain = RepEnumObj.domain;
					fldRep.value = getValue(RepEnumObj, TYPES.REP);
					if(_disabledFields == TYPES.REP)
						endInit(false);
						
					updateLocation(TYPES.REP);
				}
				
				/* QI - stands for Quick Init.
				 * This is an internal func used by the quickInit func in order to initialize the SC
				 */
				function QIsetSC(){
					var res = [];
					setLoading(TYPES.SC);
					if (!fldSC._dis){ 
						fldSC.enabled = true;		
					}
					res[0] = _location.getSc();
					var ScEnumObj = createEnumAndDefVal(res, TYPES.SC);
					if (!isValidEnumRes(ScEnumObj)){ 
						endInit();
						return;
					}
					fldSC.domain = ScEnumObj.domain;
					fldSC.value = getValue(ScEnumObj, TYPES.SC);
					if(_disabledFields == TYPES.SC)
						endInit(false);
					
					updateLocation(TYPES.SC);
				}
				
				/* QI - stands for Quick Init.
				 * This is an internal func used by the quickInit func in order to initialize the DC
				 */
				function QIsetDC(){
					var res = [];
					setLoading(TYPES.DC);
					if (!fldDC._dis){
						fldDC.enabled = true;
					}
					
					res[0] = $ENV.channel2.getDCInfo(_location, true);
					if (!isValidRes(res)) {
						setNotFound(TYPES.DC);
						return;
					}
					// since we expect an interface for the createEnumAndDefVal() function, 
					// set the name of the dc to an interface name
					res[0].setName(ImplementationToInterfaceDC(_location.getDCName()));
					var DcEnumObj = null;
					if(_qMode){
						DcEnumObj = createEnumAndDefVal(res, TYPES.DC);					
					}
					else{ //we already initiated the dc's list (_DcEnumObj), let's add it the new DC.
						var newDcEntry = entryFlavorSwitch(TYPES.DC, res[0]);
						if(_DcEnumObj && _DcEnumObj.domain){
						//inserting the new dc entry to the correct place in the DC domain (sorted array)
							updateDcDomain(_DcEnumObj.domain, newDcEntry);
						}
						else{ //if there are still no dc's at all for this user.
							_DcEnumObj = createEnumAndDefVal(res, TYPES.DC);
						}
						DcEnumObj = _DcEnumObj;
					}
					if (!isValidEnumRes(DcEnumObj)){ 
							endInit(); 
							return;
					}
					fldDC.domain = DcEnumObj.domain;
					fldDC.value = getValue(DcEnumObj, TYPES.DC);
					if(_disabledFields == TYPES.DC)
						endInit(false);
						
					updateLocation(TYPES.DC);
					
					// inserting a new DC entry to the DC's domain, keeping it sorted
					function updateDcDomain(domain, newEntry){
						removeSelectUiNotification();
						var index = searchIndexToInsert(domain, newEntry.domainEntry.value);
						var leftArray = domain.splice(0,index);
						leftArray.push(newEntry.domainEntry);
						var newDomain = leftArray.concat(domain);
						_DcEnumObj.domain = newDomain;
						
						//returning the right index to insert 'key' in the sorted array 'theList' 
						function searchIndexToInsert(theList, key){
							var mid = 0;
							var left = 0;
							var right = theList.length - 1;
							while (left <= right){
								mid = parseInt((left + right)/2);
								if (theList[mid].value < key)
									left = mid + 1;
								else
									right = mid - 1;
							}
							return left;
						}
					}
				}
	
				/**
				this function disables fields and the newDC button as well if requested
				@param newDcBtnState is bool indicating whether to enable or disable the newDC button.
				if no parameter is accepted, the setNewDCBtn function  handles it. 
				*/ 
				function endInit(newDcBtnState){
					this.setDisable(_disabledFields);
					this.setNewDCBtn(newDcBtnState);
				}
				
				/**
				 * Get current location
				 */
				function getLocation() {
					return _location;
				}
										
				
				/**
				 * Save Component current state user data
				 */
				function saveUserData(location) {
					if(location){
						saveLocationToUserData(location, _flavor);
					}
					else{
						saveLocationToUserData(getLocation(), _flavor);
					}
				}
				
				
				function setLowerBoundFlavor (flavor){
					setFlavor(flavor,DIRECTION.DOWN);
					_flavor = flavor || null;
				}
				
				function setUpperBoundFlavor (flavor){
					setFlavor(flavor,DIRECTION.UP);
					_upperFlavor = flavor || null;
				}
				
				// SETTERS / GETTES //
				
				/**
				 * Setting the flavor of this component 
				 * @param {String} flavor = TYPES enum
				 */
				function setFlavor(flavor,direction) {
					switch(flavor) {
						case TYPES.REP    : setRepFlavor(direction);    break;
						case TYPES.SC     : setSCFlavor(direction);     break;
						case TYPES.DC     : setDCFlavor(direction);     break;
						case TYPES.MODEL  : setModelFlavor(direction);  break;
						default   : break;
					}
					
				}
				
				/**
				 * Enables or Disables the "new DC" button
				 * @param {Boolean} val
				 * newBtnCell.style.display = 'block';  - meaning the button will be displayed.
				 * newBtnCell.style.display = 'none';  - meaning the button will be hidden.
				 */
				function setNewDCBtn(val) {
					if (true == val){
						newBtnCell.style.display = 'block';
					} else if (false == val){
						newBtnCell.style.display = 'none';
					} else {
						if ($ENV.isLocalRepositoryKey(fldRep.value) && fldSC.value != getSelectEntry(TYPES.SC).value && fldDC.enabled){
								newBtnCell.style.display = 'block';
						} else { 
							newBtnCell.style.display = 'none';
						}
					}
				}
				
				/**
				 * Set disable level
				 * @param type : {Object} TYPES enum
				 */
				function setDisable(type) {//disables input fields
					switch (type) {
						case TYPES.MODEL : if(fldMDL.value != getSelectEntry(type).value){
												fldMDL.enabled = false; fldMDL._dis = true;
										   }
	                    case TYPES.DC    : if(fldDC.value != getSelectEntry(type).value){
	                    						fldDC.enabled = false; fldDC._dis = true;
	                    				   }
					    case TYPES.SC    : if(fldSC.value != getSelectEntry(type).value){
					    						fldSC.enabled = false; fldSC._dis = true;
					    				   }
						case TYPES.REP   : if(fldRep.value != getSelectEntry(type).value){
												fldRep.enabled = false; fldRep._dis = true;
										   }
					}
				}
				
				 /**
				 * Set enable level
				 * @param type : {Object} TYPES enum
				 */
				function setEnable(type) {//enables input fields
					switch (type) {
						case TYPES.REP   : fldRep.enabled = true; fldRep._dis = false;
						case TYPES.SC    : fldSC.enabled  = true; fldSC._dis = false;
						case TYPES.DC    : fldDC.enabled  = true; fldDC._dis = false;
						case TYPES.MODEL : fldMDL.enabled = true; fldMDL._dis = false;
					}
				}
				
				/**
				 * Set indent size
				 * @param {Object} val = px size
				 */
				function setIndent(val) {
					val = INT(val);
					fldRep.indent = val;
					fldSC.indent = val;
					fldDC.indent = val;
					fldMDL.indent = val;
					repLabel.style.display = val ? 'none' : 'block';						
					scLabel.style.display = val ? 'none' : 'block';
					dcLabel.style.display = val ? 'none' : 'block';
					modelLabel.style.display = val ? 'none' : 'block';
				}
				
		
				/**
				returns the user data
				*/
				function getUDInteranl(){
					if(ISEMPTY(_serverUserData)){
						_serverUserData = $ENV.channel2.getUserData(true) || {};
					}
					return _serverUserData;
				}

				function getRepositoryByUrn(repUrn){
					var allRep = filterRepositoryDomain(getAllRepositories());
					for(var index in allRep){
						if(allRep[index].urn == repUrn){
							return allRep[index];
						}
					}
				}		
				
				/**
				Returns repository key
				in case there are no repositories prompt to the user and return an empty string.
				*/  
				function getFirstRepositoryKeyInner(){
					var allRep = filterRepositoryDomain(getAllRepositories());
					if(allRep && allRep.length > 0){
						return allRep[0].urn;
					}
					//if there are no repositories
					else{
						repositoryNotFound();
						return null;
					}				
				}
				
				function repositoryNotFound(){
					var repository = ' ';
					var message = '';
					setNotFound(TYPES.REP);
					switch (_forcedRepository){
						case REPOSITORY_DOMAIN.LOCAL: message = "#TEXT[XFLD_LOCSELECTOR_NOLOCREPAVAIL]";
													  repository = ' local '; 
													  break;
						case REPOSITORY_DOMAIN.SOURCE_CONTROL: message = "#TEXT[XFLD_LOCSELECTOR_NOSCREPAVAIL]"; 
															   repository = ' source control '; 
													 		   break;
						case REPOSITORY_DOMAIN.ALL: message = "#TEXT[XFLD_LOCSELECTOR_NOREPAVAIL]";
													break;
					} 
					#LOG[4,"Error - no" + repository + "repositories were found"];
					CONFIRM(message, 'OK');
					//TODO: Close the parent dialog in this case.
				}
				
				function getAllRepositories(){
					if(!_allRepositories){
						_allRepositories = $ENV.getRepositories();
					}
					return _allRepositories;		
				}
								
				/**
				 *create a location with a local or a Source Control repository, depends on the desired repository (value of member _forcedRepository)
				 */
				function createForcedLocation(){
					var ForcedLoc = $ENV.createObject('dev:Location',
								'',
								'',
								getFirstRepositoryKeyInner(),
								'',
								'',
								'',
								'',
								'');
					return ForcedLoc;
				}
					
				/**
				 * Show dropdown icons
				 */
				function setShowIcons() {
					_showIcons = true;
				}
								 
				
				function checkFlavorsBounds(){//check if bounds entered by developer are valid
					if ((_flavor && _flavor==TYPES.MODEL) ||
						 (_upperFlavor&& _upperFlavor==TYPES.REP) ||
						 (_flavor && _upperFlavor && getFlavorVal(_upperFlavor)>getFlavorVal(_flavor) )) {
						 #TRACE[4,"Wrong initialization of bounds by the developer"];// you should never get here
						 }
				}
				
				/**
				this function gets a list of all repositories and returns only the ones that correspondes to the _forcedRepository member.
				*/
				function filterRepositoryDomain(res) {
					var ans = [];		
					if (_forcedRepository == REPOSITORY_DOMAIN.ALL){
						return res;
					}
				 	else 
				 		if(_forcedRepository == REPOSITORY_DOMAIN.SOURCE_CONTROL){
				 			for(var index in res){
				 				if(!($ENV.isLocalRepositoryKey(res[index].urn))){
				 					ans.push(res[index]);
				 				}
				 			}
				 	}
				 	else 
				 		if(_forcedRepository == REPOSITORY_DOMAIN.LOCAL){
				 			for(var index in res){
				 				if($ENV.isLocalRepositoryKey(res[index].urn)){
				 					ans.push(res[index]);
				 				}
				 			}
				 	}
				return ans;
				}
							
				// PRIVATE //
				function init() {
				// This is necessary for the events of the components used by this component to work
					ENABLE_INPUTS(document.body);
    				ENABLE_EVENTS(document.body);

					checkFlavorsBounds();
					this.setNewDCBtn(false);
					var res = filterRepositoryDomain(getAllRepositories());
					
					if (!isValidRes(res)) {
						repositoryNotFound();
						return;
					}
					else if (!fldRep._dis) fldRep.enabled = true;
					var enumObj = createEnumAndDefVal(res, TYPES.REP);
					_RepEnumObj = clone(enumObj);
					if (!isValidEnumRes(enumObj)){
						return;
					}
					fldRep.domain = enumObj.domain;
					fldRep.value = getValue(enumObj, TYPES.REP);
					initSCList();
				}
				
				function initSCList() {
					updateLocation(TYPES.REP);
					this.setNewDCBtn(false);
					if (!needToContinue(TYPES.REP)){
						return;
					}
					setLoading(TYPES.SC);
					setTimeout(initSCListInner);
				}
				
				function initSCListInner() {
					//if _qMode - it means we have already initialized the locations selector using the quick init. 
					if(_qMode) return;
					var res = null;
					if(fldRep.value != getSelectEntry(TYPES.REP).value){ 
						res = ch.listSoftwareComponents(_location);
					}else{ //there is no user data
						res = null;
					}
					if (!isValidRes(res)) {
						setNotFound(TYPES.SC);
						return;
					}
					else if (!fldSC._dis){ 
						fldSC.enabled = true;		
					}
					var enumObj = createEnumAndDefVal(res, TYPES.SC);
					_ScEnumObj = clone(enumObj);
					if (!isValidEnumRes(enumObj)){
						return;
					}
					fldSC.domain = enumObj.domain;
					fldSC.value = getValue(enumObj, TYPES.SC);
					initDCList();
				}
				
				function initDCList() {
					updateLocation(TYPES.SC);
					if (!needToContinue(TYPES.SC)){
						return;
					}
					setLoading(TYPES.DC);
					setTimeout(initDCListInner);
				}
				
				function initDCListInner() {
					var res = null;
					if(fldSC.value != getSelectEntry(TYPES.SC).value){ 
						res = ch.listDCs(_location, "Im");
					}else{ //there is no relevant user data
						res = null;
					}
					if (!isValidRes(res)) {
						setNotFound(TYPES.DC);
						if(res && res.length==0){ //in case there are no dc's (empty array comes back from the server, then we enable newDc btn)
							this.setNewDCBtn();
						}
						return;
					}
					else if (!fldDC._dis) 
						fldDC.enabled = true;
					var enumObj = createEnumAndDefVal(res, TYPES.DC);
					_DcEnumObj = clone(enumObj);
					if (!isValidEnumRes(enumObj)){
						return;
					}
					fldDC.domain = enumObj.domain;
					fldDC.value = getValue(enumObj, TYPES.DC);
					this.setNewDCBtn();
					initModelList();
				}
				
				function initModelList() {
					updateLocation(TYPES.DC);
					this.setNewDCBtn();
					if (!needToContinue(TYPES.DC)){
						return;
					}
					setLoading(TYPES.MODEL);
					setTimeout(initModelListInner);
				}
				
				function initModelListInner() {
					var res = null;
					if(fldDC.value != getSelectEntry(TYPES.DC).value){ 
						res = ch.listModelsInDC(_location, true);
					}else{
						res=null;
					}
					if (!isValidRes(res)) {
						setNotFound(TYPES.MODEL);
						return;
					}else if (!fldMDL._dis) 
						fldMDL.enabled = true;
					
					var enumObj = createEnumAndDefVal(res, TYPES.MODEL);
					if (!isValidEnumRes(enumObj)){
						return;
					}
					fldMDL.domain = enumObj.domain;
					fldMDL.value = getValue(enumObj, TYPES.MODEL);
				}
				
						
				
				function isValidRes(res){
					return res && !ISEMPTY(res) && res[0];
				}
				
				
				function isSelectionValid(){
					errMsg.Error = null;
					if(this.fldRep.value == getSelectEntry(TYPES.REP).value || getNotFoundString(TYPES.REP) == this.fldRep.value){
						errMsg.Error = '#TEXT[XFLD_LOCSELECTOR_SELREP]';
						return false;
					}
					if(needToContinue(TYPES.Rep)){
						if(this.fldSC.value == getSelectEntry(TYPES.SC).value || getNotFoundString(TYPES.SC) == this.fldSC.value){
							errMsg.Error = '#TEXT[XFLD_LOCSELECTOR_SELSC]';
							return false;
						}
					}
					if(needToContinue(TYPES.SC)){
						if(this.fldDC.value == getSelectEntry(TYPES.DC).value || getNotFoundString(TYPES.DC) == this.fldDC.value){
							errMsg.Error = '#TEXT[XFLD_LOCSELECTOR_SELDC]';
							return false;
						}
					}
					if(_location && _location.isLocationValid()){
						return true;
					}
					errMsg.Error = '#TEXT[XMSG_UNKNOWN_ERROR]';
					#TRACE[4,"Essential parameters missing in the location object."];
					return false;
				}
				
				/**
				This function removes the "select repository", "select Sc", "select DC" 
				lines from the dropdown list as soon as the user clicks on one of the dropdowns
				*/
				function removeSelectUiNotification(){
						//DC
						if(_DcEnumObj!=null && _DcEnumObj.domain!=null && _DcEnumObj.domain[0].text == getSelectEntry(TYPES.DC).value && _DcEnumObj.domain.length>1){
							_DcEnumObj.domain.splice(0,1);
							fldDC.domain = _DcEnumObj.domain;
						}
						//SC
						if(_ScEnumObj!=null && _ScEnumObj.domain!=null && _ScEnumObj.domain[0].text == getSelectEntry(TYPES.SC).value && _ScEnumObj.domain.length>1){
							_ScEnumObj.domain.splice(0,1);
							fldSC.domain = _ScEnumObj.domain;
						}
						//REP
						if(_RepEnumObj!=null && _RepEnumObj.domain!=null && _RepEnumObj.domain[0].text == getSelectEntry(TYPES.REP).value && _RepEnumObj.domain.length>1){
							_RepEnumObj.domain.splice(0,1);
							fldRep.domain = _RepEnumObj.domain;
						}
				}	
				
				function clone(obj){    
				if(obj == null || typeof(obj) != 'object')        
					return obj;    
				var temp = [];    
				for(var key in obj)        
					temp[key] = clone(obj[key]);    
				return temp;
				}
				
				function createEnumAndDefVal(res, flavor) {
					var list = [];
					list.push(getSelectEntry(flavor));
					var selVal = null;
					if (flavor == TYPES.DC) _DCObj = {};
					for (var i=0, len=res.length; i<len; i++) {
						var entry = entryFlavorSwitch(flavor, res[i]);
						list.push(entry.domainEntry);
						// Update default value as the first one
						if (!selVal){ 
							selVal = (getSelectEntry(flavor)).value;	
						}
					}
					//if there is only one item in the list we remove the "-- select rep/dc/sc --" line.
					if(list.length == 2){
						list.splice(0,1);
					}
					return {domain:list, defaultVal:selVal};
				}
				
				function isValidEnumRes(enumObj) {
					if (!enumObj || !enumObj.domain || !enumObj.defaultVal) return false;
					return true;
				}
				
				function entryFlavorSwitch(flavor, resEntry) {
					switch(flavor) {
							case TYPES.REP   : return createRepEntry(resEntry);
							case TYPES.SC    : return createSCEntry(resEntry);
							case TYPES.DC    : return createDCEntry(resEntry);
							case TYPES.MODEL : return createModelEntry(resEntry);
					}
				}
				
				function getValue(enumObj, type){
				    //if there is only one item in the list we present it.
					if(enumObj.domain.length == 1){
						return enumObj.domain[0].value;
					}
					var ret = '';
					if (_isUserLocation) {
						ret = getLocationValueFromEnum(enumObj, type);
					}
					//if we have user data
					else if (hasUserData(type)) {
						 var val =  _serverUserData[_UDKEYS[type]];
						 if (isValueInDomain(val, enumObj.domain)) 
						 	ret = val;
					}					
					return ret || enumObj.defaultVal;
				}
				
				function hasUserData(type){
					_serverUserData = getUDInteranl();
					if(_serverUserData[_UDKEYS[type]] && _serverUserData[_UDKEYS[type]] !=''){
						return true;
					}
					return false;
				}
					
				function needToContinue(flavor) {
					if (getFlavorVal(_flavor) > getFlavorVal(flavor)) return true;
					return false;
				}
				
				function getFlavorVal(flavor) {
					switch(flavor) {
						case TYPES.REP     : return 1;
						case TYPES.SC      : return 2;
						case TYPES.DC      : return 3;
						case TYPES.MODEL   : return 4;
						default            : return 0;
					}
				}
				
				
				function getSelectEntry(flavor) {
					var val = getSelectText(flavor);
					return {value: val, text: val};
				}
				
				function createRepEntry(resEntry) {
					var val = resEntry.urn;
					var iconPrefix = _showIcons ? '<img src="#URL[env~skin:icons.library.gif]" align=absmiddle>&nbsp;&nbsp;' : '';
					var text = iconPrefix + resEntry.name;
					return {val:val ,domainEntry:{value: val, text: text}};
				}
				
				function createSCEntry(scEntry) {
					var val = scEntry.getSCFullName();
					var iconPrefix = _showIcons ? '<img src="#URL[env~skin:icons.softwarecomponent.gif]" align=absmiddle>&nbsp;&nbsp;' : '';
					var text = iconPrefix + val;
					return {val:val ,domainEntry:{value: val, text: text}};
				}
				
				function createDCEntry(resEntry) {
					var val = namespaceFromDC({name:resEntry.urn, vendor:resEntry.dcVendor});
					var iconPrefix = _showIcons ? '<img src="' + getDCIcon(resEntry.getState()) + '" align=absmiddle>&nbsp;&nbsp;' : '';
					var text = iconPrefix + resEntry.getId();
					var entry = {value:val, text:text};
					_DCObj[val] = resEntry;
					return {val:val, domainEntry:entry};
				}
				
				function createModelEntry(resEntry) {
					var url = resEntry.gmlObjectType && CLASS(resEntry.gmlObjectType).metadata.icon16;
					var iconPrefix = _showIcons ? '<img src="' + url + '" align=absmiddle>&nbsp;&nbsp;' : '';
					var entry = {value : resEntry.urn, text: iconPrefix + resEntry.name};
					return {val:resEntry.urn, domainEntry:entry};
				}
				
				function setLoading(flavor) {
					switch (flavor) {
							case TYPES.REP    : fldRep.setLoading();
							case TYPES.SC     : fldSC.setLoading();
							case TYPES.DC     : fldDC.setLoading();
							case TYPES.MODEL  : fldMDL.setLoading();
					}
				}
				
				function setNotFound(flavor) {
					var notFoundString = getNotFoundString(flavor);
					switch (flavor) {
							case TYPES.REP    :    setNotFoundStr(fldRep, notFoundString);	   
							case TYPES.SC     :    setNotFoundStr(fldSC,  notFoundString);
							case TYPES.DC     :    setNotFoundStr(fldDC,  notFoundString);
							case TYPES.MODEL  :    setNotFoundStr(fldMDL, notFoundString);
					}
					updateLocation(flavor);
				}

				function getNotFoundString(flavor) {
					switch (flavor) {
							case TYPES.REP    :    return "#TEXT[XFLD_LOCSELECTOR_NOREP]";	   
							case TYPES.SC     :    return "#TEXT[XFLD_LOCSELECTOR_NOSC]";
							case TYPES.DC     :    return "#TEXT[XFLD_LOCSELECTOR_NODC]";
							case TYPES.MODEL  :    return "#TEXT[XFLD_LOCSELECTOR_NOMOL]";
					}
					updateLocation(flavor);
				}
				
				function getSelectText(flavor) {
					var txt = '';
					switch (flavor) {
							case TYPES.REP    :    txt = "#TEXT[XFLD_LOCSELECTOR_SELREP]"; break;
							case TYPES.SC     :    txt = "#TEXT[XFLD_LOCSELECTOR_SELSC]"; break;
							case TYPES.DC     :    txt = "#TEXT[XFLD_LOCSELECTOR_SELDC]"; break;
							case TYPES.MODEL  :    txt = "#TEXT[XFLD_LOCSELECTOR_SELMOD]"; break;
					}
					return '-- ' + txt + ' --';
				}
				
				function setNotFoundStr(fld, txt) {
					setDropDownValue(fld, txt);
					DISABLE(fld.inputObj,true);
				}
				
				function setDropDownValue(fld, txt){
					fld.domain = JOIN([txt, txt], ":" );
				    fld.value = txt;
				}
				
				function updateLocation(flavor) {
					// Reset location object
					if (!_location) _location = $ENV.createObject("dev:Location");
					switch (flavor) {
						case TYPES.MODEL  : _location.setId( fldMDL.value );
						case TYPES.DC     : if (_DCObj[fldDC.value]) {
												_location.setDCName(_DCObj[fldDC.value].getUrn());
												_location.setDCVendor(_DCObj[fldDC.value].getDcVendor());
											}
											else { 
												_location.dc = $ENV.createObject("dev:DCProperties");
											}
						case TYPES.SC     : _location.setSCVendor( getSoftwareComponentVendor(fldSC.value) );
											_location.setSCId( getSoftwareComponentName(fldSC.value) );
						case TYPES.REP    : _location.setRepository( fldRep.value );
					}
					fireLocationChanged(flavor);
				}
				
				function getLocationValueFromEnum(enumObj, flavor) {
					if (!enumObj || (enumObj && !enumObj.domain) || !flavor) return null;
					var val = getLocationEnumVal(flavor);
					if (val) {
						var d = enumObj.domain;
						for (var k in d) {
							if (d[k] && d[k].value == val) return val;
						}
					}
					return null;
				}
				
				function getLocationEnumVal(flavor) {
					var val = '';
					try {
						switch (flavor) {
							case TYPES.MODEL  : val = _location.getId(); break;
							case TYPES.DC     : val = namespaceFromDC({name: _location.getDCName(), vendor: _location.getDCVendor()}); break;
							case TYPES.SC     : val = _location.getSCFullName(); break;
							case TYPES.REP    : val = _location.getRepository(); break;
						}
					} catch (e) {return null;}
					return val;
				}
							
				function createNewDC() {
					var res = MODAL('#URL[dev:common.NewDCDlg_Comp.htm]',
									{location: _location,
									 isLocal:true,
									 mode:'new',
									 title:'#TEXT[XTIT_SELECT_FOLDER]'},
									false);
					//if user created a new DC update the location object with the new DC name and vendor					
					if (res) {
						_location.setDCName(res.urn);
						_location.setDCVendor(res.dcVendor);
						_location.setDCId(res.urn);	
						//update the Location Selector UI with the new DC.	
						updateNewDC();
						saveUserData();
						moveFocusToParentDialog();					
					}
					else{
						moveFocusToParentDialog();
                        return;
                    }
				}
				
				//update the Location Selector UI with the new DC.
				function updateNewDC(){
					_disabledFields = null;
					_isUserLocation = true;
					QIsetDC();
				}
				
				/* Movign the focus to a field in the dialog (outside of the location selector) which is currently hosting the location selector
				 * A dialog must define a member called <_defaultFocusField> in order for it to work.
				 */
				function moveFocusToParentDialog(){
					if(window.parent && window.parent._defaultFocusField){
                    	FOCUS(window.parent._defaultFocusField);
                    }
				}
												
				function setRepFlavor(direction) {
					switch(direction) {
							case DIRECTION.UP  	    :  break;
							case DIRECTION.DOWN     : setDispNone(scRow);
													  setSCFlavor(direction);     break;
							default   : break;
						}
				}
				
				function setSCFlavor(direction) {
					switch(direction) {
							case DIRECTION.UP  	    : setDispNone(repRow);   break;
							case DIRECTION.DOWN     : setDispNone(dcRow);
													  setDCFlavor(direction);     break;
							default   : break;
						}
				}
				
				function setDCFlavor(direction) {
					switch(direction) {
							case DIRECTION.UP  	    : setDispNone(scRow);	
													  setSCFlavor(direction);   break;
							case DIRECTION.DOWN     : setDispNone(modelRow);    break;
							default   : break;
						}
	
				}
				
				function setModelFlavor(direction) {
					switch(direction) {
							case DIRECTION.UP  	    : setDispNone(dcRow);
													  setDCFlavor(direction);   break;
							case DIRECTION.DOWN     :    break;
							default   : break;
						}
				}
					
				function setDispNone(elem) {
					elem.style.display = 'none'
				}
							
				function fireLocationChanged(flavor) {
					var evt=createEventObject();
					evt.location = _location;
					evt.flavor = flavor;
					evtLocationChanged.fire(evt);
				}
				
				function isValueInDomain(val, domain){
					for (var k in domain) {
						if (domain[k].value == val) return true;
					}
					return false;
				}
				
				
				function layout() {
					elmDialog.layout();
				}
			</SCRIPT>
			
			<STYLE>
				TABLE{width:100%;}
				TD{vertical-align: middle; text-overflow:ellipsis; overflow:hidden;}
				TD.NEWDCCELL{width:1; display:none; padding-left:2px;}
				TD.FULL{width:100%;}
				TD.PAD{padding-right:5; white-space:nowrap;}
			</STYLE>
			
		</HEAD>
			
		<BODY>
			<STB:DIALOG id=elmDialog box="0 0 W H" >
				<STB:BOX box="0 0 W H">
				<TABLE align="left" cellspacing=0 border=0 cellpadding=0 style="width:100%;">
					<TR id=repRow>
						<TD id=repLabel class=PAD>#TEXT[XFLD_REP_LBL]</TD>
						<TD id=controlCell class=FULL>
							<STB:INPUT id=fldRep type="icon" onChange="initSCList()" onmousedown="removeSelectUiNotification()" loadingText="true" label="#TEXT[XFLD_REP_LBL]" style="width:100%"/>
						</TD>
					</TR>
					<TR id=scRow>
						<TD id=scLabel class=PAD>#TEXT[XFLD_SC_LBL]</TD>
						<TD  class=FULL>
							<STB:INPUT id=fldSC type="icon" onChange="initDCList()" onmousedown="removeSelectUiNotification()" loadingText="true" label="#TEXT[XFLD_SC_LBL]" style="width:100%"/>
						</TD>
					</TR>
					<TR id=dcRow>
						<TD id=dcLabel class=PAD>#TEXT[XFLD_DC_LBL]</TD>
						<TD class=FULL>
							<TABLE cellspacing=0 cellpadding=0 style="width:100%"><TR><TD style="padding-top:1; width:100%;">
							<STB:INPUT id=fldDC type="icon" onChange="initModelList()" onmousedown="removeSelectUiNotification()" loadingText="true" label="#TEXT[XFLD_DC_LBL]" style="width:100%" />
							</TD><TD id="newBtnCell" class=NEWDCCELL>
							<STB:BUTTON id=btnNewDC enabled="true" title="#TEXT[XTOL_NEW_DC]" onclick="createNewDC()">#TEXT[XBUT_NEW]...</STB:BUTTON>
							</TD></TR></TABLE>
						</TD>
					</TR>
					<TR id=modelRow>
						<TD id=modelLabel class=PAD>#TEXT[XFLD_MODEL_LBL]</TD>
						<TD  class=FULL>
							<STB:INPUT id=fldMDL type="icon" onChange="updateLocation(TYPES.MODEL)" loadingText="true" label="#TEXT[XFLD_MODEL_LBL]" style="width:100%"/>
						</TD>
					</TR>
				</TABLE>
				</STB:BOX>
			</STB:DIALOG>
		</BODY>
	</HTML>	

</PUBLIC:COMPONENT>