srcanaapps/apiquerytool/com.nokia.s60tools.apiquery.cache/src/com/nokia/s60tools/apiquery/cache/searchmethod/LocalCacheSearchMethodExtension.java
changeset 0 a02c979e8dfd
equal deleted inserted replaced
-1:000000000000 0:a02c979e8dfd
       
     1 /*
       
     2 * Copyright (c) 2007 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */ 
       
    17  
       
    18 package com.nokia.s60tools.apiquery.cache.searchmethod;
       
    19 
       
    20 import java.io.IOException;
       
    21 import java.net.URI;
       
    22 import java.util.ArrayList;
       
    23 import java.util.Collection;
       
    24 import java.util.Hashtable;
       
    25 import java.util.Set;
       
    26 
       
    27 import org.eclipse.core.runtime.CoreException;
       
    28 import org.eclipse.core.runtime.IConfigurationElement;
       
    29 import org.eclipse.core.runtime.IExecutableExtension;
       
    30 import org.eclipse.core.runtime.IProgressMonitor;
       
    31 import org.eclipse.core.runtime.IStatus;
       
    32 import org.eclipse.core.runtime.jobs.IJobChangeEvent;
       
    33 import org.eclipse.core.runtime.jobs.IJobChangeListener;
       
    34 import org.eclipse.core.runtime.jobs.Job;
       
    35 import org.eclipse.swt.widgets.Composite;
       
    36 import org.eclipse.swt.widgets.Display;
       
    37 import org.eclipse.ui.IWorkbench;
       
    38 import org.eclipse.ui.PlatformUI;
       
    39 import org.eclipse.ui.browser.IWebBrowser;
       
    40 
       
    41 
       
    42 
       
    43 import com.nokia.s60tools.apiquery.cache.configuration.CacheEntry;
       
    44 import com.nokia.s60tools.apiquery.cache.configuration.CacheEntryStorage;
       
    45 import com.nokia.s60tools.apiquery.cache.core.job.UpdateSDKSelectionJob;
       
    46 import com.nokia.s60tools.apiquery.cache.resources.Messages;
       
    47 import com.nokia.s60tools.apiquery.cache.searchmethod.ui.LocalCacheUIComposite;
       
    48 import com.nokia.s60tools.apiquery.cache.util.SDKFinder;
       
    49 import com.nokia.s60tools.apiquery.cache.util.SDKUtil;
       
    50 import com.nokia.s60tools.apiquery.cache.xml.MetadataXMLToUIMappingRules;
       
    51 import com.nokia.s60tools.apiquery.popup.actions.OpenFileAction;
       
    52 import com.nokia.s60tools.apiquery.shared.datatypes.APIDetailField;
       
    53 import com.nokia.s60tools.apiquery.shared.datatypes.APIDetails;
       
    54 import com.nokia.s60tools.apiquery.shared.datatypes.APIQueryParameters;
       
    55 import com.nokia.s60tools.apiquery.shared.datatypes.APIShortDescription;
       
    56 import com.nokia.s60tools.apiquery.shared.datatypes.APIShortDescriptionSearchResults;
       
    57 import com.nokia.s60tools.apiquery.shared.datatypes.config.AbstractEntry;
       
    58 import com.nokia.s60tools.apiquery.shared.datatypes.config.AbstractEntryStorage;
       
    59 import com.nokia.s60tools.apiquery.shared.exceptions.QueryOperationFailedException;
       
    60 import com.nokia.s60tools.apiquery.shared.exceptions.XMLNotValidException;
       
    61 import com.nokia.s60tools.apiquery.shared.searchmethod.AbstractSearchMethodExtension;
       
    62 import com.nokia.s60tools.apiquery.shared.searchmethod.ISearchMethodExtension;
       
    63 import com.nokia.s60tools.apiquery.shared.searchmethod.SearchMethodExtensionInfo;
       
    64 import com.nokia.s60tools.apiquery.shared.searchmethod.ui.AbstractUiFractionComposite;
       
    65 import com.nokia.s60tools.apiquery.shared.services.QueryServices;
       
    66 import com.nokia.s60tools.apiquery.shared.util.console.APIQueryConsole;
       
    67 import com.nokia.s60tools.apiquery.shared.util.xml.XMLUtils;
       
    68 import com.nokia.s60tools.sdk.SdkInformation;
       
    69 import com.nokia.s60tools.util.debug.DbgUtility;
       
    70 
       
    71 /**
       
    72  * Search Method extension allowing to create local caches from the web server
       
    73  * entries, and used the cached information instead of the online information.
       
    74  */
       
    75 public class LocalCacheSearchMethodExtension implements  ISearchMethodExtension, IExecutableExtension, IJobChangeListener
       
    76 {
       
    77 	
       
    78 	/**
       
    79 	 * This class is created by using <code>createExecutableExtension</code>
       
    80 	 * method from <code>IConfigurationElement</code> class, and therefore the
       
    81 	 * constructor cannot have any parameters.
       
    82 	 * 
       
    83 	 * @see org.eclipse.core.runtime.IConfigurationElement#createExecutableExtension
       
    84 	 */
       
    85 	public LocalCacheSearchMethodExtension(){
       
    86 		extensionInfo = new SearchMethodExtensionInfo();			
       
    87 	}
       
    88 	
       
    89 	private SearchMethodExtensionInfo extensionInfo;
       
    90 	private APIQueryParameters apiQueryParameters = null;
       
    91 		
       
    92 
       
    93 
       
    94 	/*
       
    95 	 * (non-Javadoc)
       
    96 	 * 
       
    97 	 * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement,
       
    98 	 *      java.lang.String, java.lang.Object)
       
    99 	 */
       
   100 	public void setInitializationData(IConfigurationElement configElem, String classPropertyName, Object data) throws CoreException {
       
   101 		extensionInfo.setId(configElem.getAttribute(AbstractSearchMethodExtension.ID_ATTRIBUTE));
       
   102 		extensionInfo.setDescription(configElem.getAttribute(AbstractSearchMethodExtension.DESCRIPTION_ATTRIBUTE));
       
   103 		extensionInfo.setDefault(Boolean.parseBoolean(configElem.getAttribute(AbstractSearchMethodExtension.IS_DEFAULT_ATTRIBUTE)));
       
   104 	}
       
   105 
       
   106 	/*
       
   107 	 * (non-Javadoc)
       
   108 	 * 
       
   109 	 * @see com.nokia.s60tools.apiquery.shared.searchmethod.ISearchMethodExtension#getExtensionInfo()
       
   110 	 */
       
   111 	public SearchMethodExtensionInfo getExtensionInfo() {
       
   112 		return extensionInfo;
       
   113 	}	
       
   114 	
       
   115 	/*
       
   116 	 * (non-Javadoc)
       
   117 	 * 
       
   118 	 * @see com.nokia.s60tools.apiquery.searchmethodregistry.ISearchMethodExtension#notifyExtensionShutdown()
       
   119 	 */
       
   120 	public void notifyExtensionShutdown() {
       
   121 		// Currently nothing to do
       
   122 	}
       
   123 
       
   124 	/*
       
   125 	 * (non-Javadoc)
       
   126 	 * 
       
   127 	 * @see com.nokia.s60tools.apiquery.searchmethodregistry.ISearchMethodExtension#createExtensionConfigurationUi(org.eclipse.swt.widgets.Composite)
       
   128 	 */
       
   129 	public AbstractUiFractionComposite createExtensionConfigurationUi(Composite parent) {
       
   130 		return new LocalCacheUIComposite(parent);
       
   131 	}
       
   132 
       
   133 	/*
       
   134 	 * (non-Javadoc)
       
   135 	 * 
       
   136 	 * @see com.nokia.s60tools.apiquery.shared.searchmethod.ISearchMethodExtension#isSupportedQueryType(int)
       
   137 	 */
       
   138 	public boolean isSupportedQueryType(int queryType) {
       
   139 		// By default the query type is not supported.
       
   140 		boolean isSupported = false;
       
   141 		
       
   142 		switch (queryType) {
       
   143 		
       
   144 	     	// Flow through (supported types)
       
   145 			case APIQueryParameters.QUERY_BY_API_NAME:
       
   146 			case APIQueryParameters.QUERY_BY_SUBSYSTEM_NAME:
       
   147 			case APIQueryParameters.QUERY_BY_LIB_NAME:
       
   148 			case APIQueryParameters.QUERY_BY_HEADER_NAME:
       
   149 				 isSupported = true;
       
   150 			     break;
       
   151 			     
       
   152 			default:
       
   153 				break;
       
   154 		}
       
   155 
       
   156 		return isSupported;
       
   157 	}
       
   158 
       
   159 	/*
       
   160 	 * (non-Javadoc)
       
   161 	 * 
       
   162 	 * @see com.nokia.s60tools.apiquery.shared.searchmethod.ISearchMethodExtension#getAPIDetails(com.nokia.s60tools.apiquery.shared.datatypes.APIShortDescription)
       
   163 	 */
       
   164 	public APIDetails getAPIDetails(APIShortDescription summary) throws QueryOperationFailedException {
       
   165 		
       
   166 		CacheEntryStorage storage = CacheEntryStorage.getInstance();
       
   167 		if(!storage.isLoaded()){
       
   168 			startUpdateJobAndWaitUntilFinished(storage);		
       
   169 		}
       
   170 		
       
   171 		APIDetails details = null;
       
   172 	
       
   173 		CacheEntry entry = (CacheEntry) storage.getByEntryId(summary.getSource());		
       
   174 		details = entry.getAPIDetails();		
       
   175 		return details;				
       
   176 	}	
       
   177 	
       
   178 
       
   179 
       
   180 	/*
       
   181 	 * (non-Javadoc)
       
   182 	 * 
       
   183 	 * @see com.nokia.s60tools.apiquery.shared.searchmethod.ISearchMethodExtension#getEntryStorageInstance()
       
   184 	 */
       
   185 	public AbstractEntryStorage getEntryStorageInstance() {
       
   186 		return CacheEntryStorage.getInstance();
       
   187 	}
       
   188 
       
   189 
       
   190 	
       
   191 	/**
       
   192 	 * Handles (run) query for one entry
       
   193 	 * 
       
   194 	 * @param parameters
       
   195 	 * @param runSynchronous
       
   196 	 * @return APIs matching search criteria
       
   197 	 * @throws QueryOperationFailedException
       
   198 	 */
       
   199 	private Collection<APIShortDescription> handleSingleEntryQuery(APIQueryParameters parameters, boolean runSynchronous) throws QueryOperationFailedException {
       
   200 		
       
   201 		ArrayList<APIShortDescription> summary = null;
       
   202 		// Create a job to convert needed Excel If sheets to XML format
       
   203 		try {
       
   204 				summary = getSummarys(parameters, runSynchronous);
       
   205 		} catch (Exception e1) {
       
   206 			examineAndHandleQueryFailureException(e1);
       
   207 		}
       
   208 		
       
   209 		return summary;
       
   210 		
       
   211 	}
       
   212 	
       
   213 	
       
   214 	/*
       
   215 	 * (non-Javadoc)
       
   216 	 * 
       
   217 	 * @see com.nokia.s60tools.apiquery.shared.searchmethod.ISearchMethodExtension#runAPIQuery(com.nokia.s60tools.apiquery.shared.datatypes.APIQueryParameters)
       
   218 	 */
       
   219 	public APIShortDescriptionSearchResults runAPIQuery(APIQueryParameters parameters) {
       
   220 		
       
   221 		this.apiQueryParameters  = parameters;
       
   222 		// Owerwriting query for if sheets, because of usually there is multiple
       
   223 		// (>100) data sources
       
   224 		APIShortDescriptionSearchResults results = new APIShortDescriptionSearchResults();
       
   225 
       
   226 		try {
       
   227 			// Making query for each configured and selected server entry.
       
   228 			AbstractEntry[] selEntryArr = getEntryStorageInstance().getSelectedEntries();
       
   229 			
       
   230 			// Were any entries configured or selected?
       
   231 			if(selEntryArr.length == 0){
       
   232 				throw new QueryOperationFailedException(Messages.getString("LocalCacheSearchMethodExtension.No_Server_Entries_ErrMsg")); //$NON-NLS-1$
       
   233 			}
       
   234 			
       
   235 			boolean runSynchronous = !parameters.isQueryFromUI();// If query
       
   236 																	// comes
       
   237 																	// from UI,
       
   238 																	// running
       
   239 																	// async, if
       
   240 																	// not,
       
   241 																	// running
       
   242 																	// sync
       
   243 			
       
   244 			// If there was semi-comma separated search items or not
       
   245 			if (parameters.getSearchString().contains(
       
   246 					APIQueryParameters.SEARCH_ITEM_SEPARATOR_CHAR)) {
       
   247 				results.addSearchResults(handleMultiEntryQuery(parameters, runSynchronous));
       
   248 			} else {
       
   249 				results.addSearchResults(handleSingleEntryQuery(parameters, runSynchronous));
       
   250 			}
       
   251 		}catch(QueryOperationFailedException e){
       
   252 			results.addSearchError(e);
       
   253 		}
       
   254 		catch (Exception e) {
       
   255 			e.printStackTrace();
       
   256 			results.addSearchError( new QueryOperationFailedException(e.getMessage()));
       
   257 		}
       
   258 		
       
   259 		return results;
       
   260 	}		
       
   261 	
       
   262 	/**
       
   263 	 * Get APIShortDescriptions from XML Excel If Sheet XML files.
       
   264 	 * 
       
   265 	 * @return
       
   266 	 * @throws QueryOperationFailedException
       
   267 	 */
       
   268 	private ArrayList<APIShortDescription> getSummarys( APIQueryParameters parameters, boolean runSynchronous) throws QueryOperationFailedException {
       
   269 		ArrayList<APIShortDescription> summary = new ArrayList<APIShortDescription>();
       
   270 		String curId = "";//$NON-NLS-1$
       
   271 		try {		
       
   272 			CacheEntryStorage storage = CacheEntryStorage.getInstance();
       
   273 			Collection<AbstractEntry> selectedAPIs = storage.getSelectedEntriesCollection();
       
   274 			
       
   275 			// if storage is not loaded, e.g. this is first time of searching
       
   276 			// after Carbide is started up, must load data first
       
   277 			if(!storage.isLoaded() && !runSynchronous){
       
   278 				startUpdateJobAndRunQueryWhenFinished(storage);
       
   279 			}
       
   280 			else{
       
   281 				if(!storage.isLoaded()){
       
   282 					startUpdateJobAndWaitUntilFinished(storage);
       
   283 				}				
       
   284 			
       
   285 				String [] searchStrings = new String []{parameters.getSearchString()};			
       
   286 	
       
   287 				
       
   288 				// Try to found search string from selected search method
       
   289 				// (selected field from XML data)
       
   290 				for (AbstractEntry abstractEntry : selectedAPIs) {
       
   291 					
       
   292 					CacheEntry entry = (CacheEntry)abstractEntry;
       
   293 					
       
   294 					APIDetails det = entry.getAPIDetails();
       
   295 					if(det == null){
       
   296 						APIQueryConsole.getInstance().println(Messages.getString("LocalCacheSearchMethodExtension.UnexpectedEntryErrMsg") +entry.getId()); //$NON-NLS-1$
       
   297 						continue;// Should not be able to occur, because load
       
   298 									// deselects source if load fails
       
   299 					}
       
   300 					curId =  entry.getId(); 
       
   301 					String curSourceDesc = entry.getName() ;
       
   302 					// Select Field from APIDetail, by selected search type, to
       
   303 					// found if that field contais the search string
       
   304 					APIDetailField fieldToSearchFor = getSelectedSearchField(det, parameters.getQueryType());
       
   305 					String fieldValueToSearch = fieldToSearchFor.getValue();
       
   306 					String apiName = det.getDetail(MetadataXMLToUIMappingRules.NAME).getValue();
       
   307 	
       
   308 					DbgUtility.println(DbgUtility.PRIORITY_LOOP, "From API: " +//$NON-NLS-1$
       
   309 							apiName
       
   310 							+", file: " + curId //$NON-NLS-1$
       
   311 							+", querytype: " +parameters.getQueryType()//$NON-NLS-1$
       
   312 							+ ", foundig values to search for: " +fieldValueToSearch);//$NON-NLS-1$
       
   313 					
       
   314 					// Looking for all search strings if there was semi-comma
       
   315 					// separated strings to search for
       
   316 					for (int i = 0; i < searchStrings.length; i++) {
       
   317 						boolean matchs;
       
   318 						if(apiQueryParameters.isExactMatchInUse()){
       
   319 							// If exact match is in use, using equals as match
       
   320 							matchs = fieldValueToSearch.equalsIgnoreCase(searchStrings[i]);
       
   321 						}
       
   322 						else{
       
   323 							// If exact match is not in use, and if result
       
   324 							// contains search string (case insensitive)
       
   325 							matchs = fieldValueToSearch.toLowerCase().contains(searchStrings[i].toLowerCase());
       
   326 						}
       
   327 						// If result matches to search string, creating new API
       
   328 						// Summary object and add it to result
       
   329 
       
   330 						if(matchs){
       
   331 							APIShortDescription sum = new APIShortDescription(
       
   332 									apiName
       
   333 									,curId,
       
   334 									curSourceDesc);
       
   335 							// If API Details should be added to description
       
   336 							// then adding it
       
   337 							if(parameters.isDetailsMentToAddToDescriptions()){
       
   338 								sum.setAPIDetails(det);
       
   339 							}
       
   340 							summary.add(sum);
       
   341 						}					
       
   342 					}
       
   343 				}
       
   344 			}
       
   345 		
       
   346 		} catch (Exception e) {
       
   347 			DbgUtility.println(DbgUtility.PRIORITY_OPERATION, "Error when handling file: " + curId);//$NON-NLS-1$
       
   348 			e.printStackTrace();
       
   349 			examineAndHandleQueryFailureException(e);
       
   350 		}
       
   351 		return summary;
       
   352 	}
       
   353 
       
   354 	/**
       
   355 	 * Update (load) data sources if not loaded yet, after done, launch real
       
   356 	 * query
       
   357 	 * 
       
   358 	 * @param storage
       
   359 	 * @throws QueryOperationFailedException
       
   360 	 */
       
   361 	private void startUpdateJobAndRunQueryWhenFinished(CacheEntryStorage storage)
       
   362 			throws QueryOperationFailedException {
       
   363 
       
   364 		try {		
       
   365 			
       
   366 			SdkInformation info = SDKFinder.getSDKInformation(storage.getCurrentlySelectedSDKID());
       
   367 			UpdateSDKSelectionJob job = new UpdateSDKSelectionJob(Messages.getString("LocalCacheSearchMethodExtension.UpdatingDataSourceMsg_Part1") +info.getSdkId() +Messages.getString("LocalCacheSearchMethodExtension.UpdatingDataSourceMsg_Part2"), info, false); //$NON-NLS-1$ //$NON-NLS-2$
       
   368 			if(job.isAllreadyRunning()){
       
   369 				return;
       
   370 			}
       
   371 			job.setPriority(Job.DECORATE);			
       
   372 			job.addJobChangeListener(this);
       
   373 			job.schedule();
       
   374 
       
   375 		} catch (Exception e) {
       
   376 			e.printStackTrace();
       
   377 			examineAndHandleQueryFailureException(e);
       
   378 		}
       
   379 	}	
       
   380 	
       
   381 	/**
       
   382 	 * Update (load) data sources if not loaded yet, after done, launch real
       
   383 	 * query
       
   384 	 * 
       
   385 	 * @param storage
       
   386 	 * @throws QueryOperationFailedException
       
   387 	 */
       
   388 	private void startUpdateJobAndWaitUntilFinished(CacheEntryStorage storage)
       
   389 			throws QueryOperationFailedException {
       
   390 
       
   391 		try {		
       
   392 			
       
   393 			SdkInformation info = SDKFinder.getSDKInformation(storage.getCurrentlySelectedSDKID());
       
   394 			UpdateSDKSelectionJob job = new UpdateSDKSelectionJob(Messages.getString("LocalCacheSearchMethodExtension.UpdatingDataSourceMsg_Part1") +info.getSdkId() +Messages.getString("LocalCacheSearchMethodExtension.UpdatingDataSourceMsg_Part2"), info, false); //$NON-NLS-1$ //$NON-NLS-2$
       
   395 			if(job.isAllreadyRunning()){
       
   396 				return;
       
   397 			}
       
   398 			job.setPriority(Job.DECORATE);
       
   399 			job.schedule();
       
   400 			job.join();
       
   401 
       
   402 		} catch (Exception e) {
       
   403 			e.printStackTrace();
       
   404 			examineAndHandleQueryFailureException(e);
       
   405 		}
       
   406 	}	
       
   407 	
       
   408 	
       
   409 	/**
       
   410 	 * get search field by query type
       
   411 	 * 
       
   412 	 * @param det
       
   413 	 * @param queryType
       
   414 	 * @return
       
   415 	 */
       
   416 	private APIDetailField getSelectedSearchField(APIDetails det, int queryType) {
       
   417 				
       
   418 		APIDetailField field;
       
   419 		switch (queryType) {
       
   420 		case APIQueryParameters.QUERY_BY_API_NAME:
       
   421 			field = det.getDetail(MetadataXMLToUIMappingRules.NAME);
       
   422 			break;
       
   423 		case APIQueryParameters.QUERY_BY_SUBSYSTEM_NAME:
       
   424 			field = det.getDetail(MetadataXMLToUIMappingRules.SUBSYSTEM);
       
   425 			break;
       
   426 		case APIQueryParameters.QUERY_BY_LIB_NAME:
       
   427 			field = det.getDetail(MetadataXMLToUIMappingRules.LIBS);
       
   428 			break;
       
   429 		case APIQueryParameters.QUERY_BY_HEADER_NAME:
       
   430 			field = det.getDetail(MetadataXMLToUIMappingRules.HEADERS);
       
   431 			break;
       
   432 		default:
       
   433 			field = det.getDetail(MetadataXMLToUIMappingRules.NAME);
       
   434 			break;
       
   435 		}		
       
   436 		return field;
       
   437 	}	
       
   438 
       
   439 
       
   440 	/**
       
   441 	 * Handles (run) query for several search strings
       
   442 	 * 
       
   443 	 * @param parameters
       
   444 	 * @param runSynchronous
       
   445 	 * @return APIs matching search criteria
       
   446 	 * @throws QueryOperationFailedException
       
   447 	 */
       
   448 	private Collection<APIShortDescription> handleMultiEntryQuery(APIQueryParameters parameters, boolean runSynchronous) throws QueryOperationFailedException {
       
   449 		
       
   450 		// Using table to make sure that same API:s does not exist more than
       
   451 		// once
       
   452 		Hashtable<String, APIShortDescription> summary  = new Hashtable<String, APIShortDescription>();
       
   453 		String [] searchStrings = parameters.getSearchString().split(APIQueryParameters.SEARCH_ITEM_SEPARATOR_CHAR);
       
   454 		
       
   455 		APIQueryParameters param ;
       
   456 		Collection<APIShortDescription>  temp;
       
   457 		// Adding all APIDetails to collection one by one
       
   458 		for (int i = 0; i < searchStrings.length; i++) {
       
   459 			param = new APIQueryParameters(parameters.getQueryType(), searchStrings[i]);
       
   460 
       
   461 			temp = handleSingleEntryQuery(param, runSynchronous);
       
   462 			for (APIShortDescription api : temp) {
       
   463 				summary.put(api.getName(), api);// One API can contain in
       
   464 												// results only once. HashTable
       
   465 												// does not allow multiple
       
   466 												// occurances as keys.
       
   467 			}			
       
   468 
       
   469 		}		
       
   470 		return summary.values();
       
   471 	}
       
   472 	
       
   473 	/*
       
   474 	 * (non-Javadoc)
       
   475 	 * 
       
   476 	 * @see com.nokia.s60tools.apiquery.shared.searchmethod.ISearchMethodExtension#getAPIDetails(java.util.Collection)
       
   477 	 */
       
   478 	public Hashtable<String, APIDetails> getAPIDetails(Collection<APIShortDescription> apis) throws QueryOperationFailedException {
       
   479 
       
   480 		CacheEntryStorage storage = CacheEntryStorage.getInstance();
       
   481 		if(!storage.isLoaded()){
       
   482 			startUpdateJobAndWaitUntilFinished(storage);		
       
   483 		}
       
   484 		
       
   485 		Hashtable<String, APIDetails> apiDetails = new Hashtable<String, APIDetails>(apis.size());
       
   486 		for (APIShortDescription summary : apis) {
       
   487 			apiDetails.put(summary.getName(), getAPIDetails(summary));
       
   488 		}
       
   489 		return apiDetails;
       
   490 	}	
       
   491 	
       
   492 	/**
       
   493 	 * Examines the type of throwable parameter, and adds appropriate error
       
   494 	 * message or default message, and forwards the information for further
       
   495 	 * processing.
       
   496 	 * 
       
   497 	 * @param throwable
       
   498 	 *            Throwable to be examined.
       
   499 	 * @throws QueryOperationFailedException
       
   500 	 */
       
   501 	private void examineAndHandleQueryFailureException(Throwable throwable) throws QueryOperationFailedException{
       
   502 		
       
   503 		String errMsg = Messages.getString("LocalCacheSearchMethodExtension.UnexpectedException_ErrMsg"); //$NON-NLS-1$
       
   504 		
       
   505 		if(throwable instanceof IOException) {
       
   506 			errMsg = Messages.getString("LocalCacheSearchMethodExtension.IOException_ErrMsg"); //$NON-NLS-1$
       
   507 		}
       
   508 		else if(throwable instanceof XMLNotValidException) {
       
   509 			errMsg = Messages.getString("LocalCacheSearchMethodExtension.InvalidXML_ErrMsg"); //$NON-NLS-1$
       
   510 		} 
       
   511 		
       
   512 		queryFailed(errMsg, throwable.getMessage());
       
   513 	}
       
   514 	/**
       
   515 	 * Throws an exception for user with the given message.
       
   516 	 * 
       
   517 	 * @param errorMsg
       
   518 	 *            Main error message for the user.
       
   519 	 * @param detailedMsg
       
   520 	 *            More detailed message shown in parenthesis.
       
   521 	 * @throws QueryOperationFailedException
       
   522 	 */
       
   523 	private void queryFailed(String errorMsg, String detailedMsg) throws QueryOperationFailedException {
       
   524 		APIQueryConsole.getInstance().println(errorMsg, APIQueryConsole.MSG_ERROR);
       
   525 		String combinedMsg = errorMsg + " (" + detailedMsg + ")."; //$NON-NLS-1$ //$NON-NLS-2$
       
   526 		throw new QueryOperationFailedException(combinedMsg);
       
   527 	}	
       
   528 	
       
   529 	
       
   530 	/*
       
   531 	 * (non-Javadoc)
       
   532 	 * 
       
   533 	 * @see org.eclipse.core.runtime.jobs.IJobChangeListener#done(org.eclipse.core.runtime.jobs.IJobChangeEvent)
       
   534 	 *      When data sources (metadata) is loaded, running real query
       
   535 	 * @see com.nokia.s60tools.apiquery.ui.views.main.MainView#runAPIQueryFromExternalClass(int,
       
   536 	 *      java.lang.String)
       
   537 	 */
       
   538 	public void done(IJobChangeEvent event) {
       
   539 		
       
   540 		Job job = event.getJob();
       
   541 		UpdateSDKSelectionJob ifsJob = (UpdateSDKSelectionJob)job;
       
   542 		ifsJob.reportEndTime();
       
   543 		IStatus status = ifsJob.getResult();
       
   544 
       
   545 		// Chekc that job status was ok before launching query
       
   546 		if( status != null && status.getSeverity() == IStatus.OK) { 
       
   547 		
       
   548 			// Launching the the real query when XML:s was generated
       
   549 			Runnable runQueryRunnable = new Runnable(){
       
   550 				public void run(){
       
   551 					try {
       
   552 						QueryServices.runAPIQuery(apiQueryParameters.getQueryType(),
       
   553 								apiQueryParameters.getSearchString());
       
   554 					} catch (QueryOperationFailedException e) {
       
   555 						APIQueryConsole.getInstance().println(Messages.getString("LocalCacheSearchMethodExtension.Failed_To_Start_Query_ErrMsg")  //$NON-NLS-1$
       
   556 								+e.getMessage(), APIQueryConsole.MSG_ERROR);
       
   557 						e.printStackTrace();
       
   558 					}
       
   559 				}
       
   560 			};
       
   561 						
       
   562 			// Showing a visible message has to be done in its own thread
       
   563 			// in order not to cause invalid thread access
       
   564 			Display.getDefault().asyncExec(runQueryRunnable);        	
       
   565 		}
       
   566 		
       
   567 	}
       
   568 
       
   569 	/*
       
   570 	 * (non-Javadoc)
       
   571 	 * 
       
   572 	 * @see org.eclipse.core.runtime.jobs.IJobChangeListener#aboutToRun(org.eclipse.core.runtime.jobs.IJobChangeEvent)
       
   573 	 */
       
   574 	public void aboutToRun(IJobChangeEvent event) {
       
   575 		// Not needed
       
   576 	}
       
   577 
       
   578 	/*
       
   579 	 * (non-Javadoc)
       
   580 	 * 
       
   581 	 * @see org.eclipse.core.runtime.jobs.IJobChangeListener#awake(org.eclipse.core.runtime.jobs.IJobChangeEvent)
       
   582 	 */
       
   583 	public void awake(IJobChangeEvent event) {
       
   584 		// Not needed
       
   585 	}
       
   586 
       
   587 	/*
       
   588 	 * (non-Javadoc)
       
   589 	 * 
       
   590 	 * @see org.eclipse.core.runtime.jobs.IJobChangeListener#running(org.eclipse.core.runtime.jobs.IJobChangeEvent)
       
   591 	 */
       
   592 	public void running(IJobChangeEvent event) {
       
   593 		// Not needed
       
   594 	}
       
   595 
       
   596 	/*
       
   597 	 * (non-Javadoc)
       
   598 	 * 
       
   599 	 * @see org.eclipse.core.runtime.jobs.IJobChangeListener#scheduled(org.eclipse.core.runtime.jobs.IJobChangeEvent)
       
   600 	 */
       
   601 	public void scheduled(IJobChangeEvent event) {
       
   602 		// Not needed
       
   603 	}
       
   604 
       
   605 	/*
       
   606 	 * (non-Javadoc)
       
   607 	 * 
       
   608 	 * @see org.eclipse.core.runtime.jobs.IJobChangeListener#sleeping(org.eclipse.core.runtime.jobs.IJobChangeEvent)
       
   609 	 */
       
   610 	public void sleeping(IJobChangeEvent event) {
       
   611 		// Not needed
       
   612 	}	
       
   613 	
       
   614 	/*
       
   615 	 * (non-Javadoc)
       
   616 	 * 
       
   617 	 * @see com.nokia.s60tools.apiquery.shared.searchmethod.ISearchMethodExtension#getAPIDetailsToReport()
       
   618 	 */
       
   619 	public String[] getAPIDetailsToReport(Set <String> usedAPIs, Hashtable<String, APIDetails> projectUsingAPIDetails) {
       
   620 		
       
   621 		boolean containsCollection = false;
       
   622 		boolean containsSubsystem = false;
       
   623 		for (String api : usedAPIs) {
       
   624 			APIDetails det = projectUsingAPIDetails.get(api);
       
   625 			if(det == null || det.getKeys() == null){
       
   626 				continue;
       
   627 			}
       
   628 			if(det.getKeys().contains(MetadataXMLToUIMappingRules.COLLECTION)){
       
   629 				containsCollection = true;
       
   630 			}
       
   631 			if(det.getKeys().contains(MetadataXMLToUIMappingRules.SUBSYSTEM)){
       
   632 				containsSubsystem = true;
       
   633 			}	
       
   634 			// If we found occurrence of both subsystems version (sybsystem in
       
   635 			// data version 1.0 collection in data version 2.0)
       
   636 			// we can continue because then both headers will occur in report
       
   637 			// anyway
       
   638 			if(containsCollection && containsSubsystem){
       
   639 				break;
       
   640 			}
       
   641 		}
       
   642 		
       
   643 		String [] apiDetailsToReport;
       
   644 		
       
   645 		// If both subsystem versions is found
       
   646 		if(containsCollection && containsSubsystem){
       
   647 			apiDetailsToReport= new String []{
       
   648 				MetadataXMLToUIMappingRules.COLLECTION,
       
   649 				MetadataXMLToUIMappingRules.SUBSYSTEM,
       
   650 				MetadataXMLToUIMappingRules.RELEASE_CATEGORY,
       
   651 				MetadataXMLToUIMappingRules.RELEASE_SINCE_VERSION,
       
   652 				MetadataXMLToUIMappingRules.RELEASE_DEPRECATED_SINCE_VERSION,
       
   653 				MetadataXMLToUIMappingRules.LIBS		
       
   654 			};
       
   655 		}
       
   656 		// if we found only collections, not subsystems
       
   657 		else if(containsCollection && !containsSubsystem){
       
   658 			apiDetailsToReport= new String []{
       
   659 				MetadataXMLToUIMappingRules.COLLECTION,
       
   660 				MetadataXMLToUIMappingRules.RELEASE_CATEGORY,
       
   661 				MetadataXMLToUIMappingRules.RELEASE_SINCE_VERSION,
       
   662 				MetadataXMLToUIMappingRules.RELEASE_DEPRECATED_SINCE_VERSION,
       
   663 				MetadataXMLToUIMappingRules.LIBS		
       
   664 			};
       
   665 		}
       
   666 		// else if we dont found collections or we did not found anything, using
       
   667 		// subsystem as default value
       
   668 		else {// if(!containsCollection){
       
   669 			apiDetailsToReport= new String []{
       
   670 				MetadataXMLToUIMappingRules.SUBSYSTEM,
       
   671 				MetadataXMLToUIMappingRules.RELEASE_CATEGORY,
       
   672 				MetadataXMLToUIMappingRules.RELEASE_SINCE_VERSION,
       
   673 				MetadataXMLToUIMappingRules.RELEASE_DEPRECATED_SINCE_VERSION,
       
   674 				MetadataXMLToUIMappingRules.LIBS		
       
   675 			};
       
   676 		}				
       
   677 		return apiDetailsToReport;
       
   678 	}	
       
   679 	
       
   680 	/**
       
   681 	 * Maps query type to API Detail topic in API Details.
       
   682 	 * 
       
   683 	 * @param queryType
       
   684 	 *            Query type constant.
       
   685 	 * @return Name of the API Detail.
       
   686 	 */
       
   687 	public String getAPIDetailNameInDetailsByQueryType(int queryType){
       
   688 		
       
   689 		String apiDetail = null;
       
   690 		
       
   691 		switch (queryType) {
       
   692 
       
   693 		case APIQueryParameters.QUERY_BY_API_NAME:
       
   694 			apiDetail = MetadataXMLToUIMappingRules.NAME;
       
   695 			break;
       
   696 
       
   697 		case APIQueryParameters.QUERY_BY_SUBSYSTEM_NAME:
       
   698 			apiDetail = MetadataXMLToUIMappingRules.SUBSYSTEM;
       
   699 			break;
       
   700 
       
   701 		case APIQueryParameters.QUERY_BY_DLL_NAME:
       
   702 			apiDetail = XMLUtils.DESCRIPTION_DLLS;
       
   703 			break;
       
   704 
       
   705 		case APIQueryParameters.QUERY_BY_LIB_NAME:
       
   706 			apiDetail = MetadataXMLToUIMappingRules.LIBS;
       
   707 			break;
       
   708 
       
   709 		case APIQueryParameters.QUERY_BY_HEADER_NAME:
       
   710 			apiDetail = MetadataXMLToUIMappingRules.HEADERS;
       
   711 			break;
       
   712 
       
   713 		case APIQueryParameters.QUERY_BY_CRPS_KEY_NAME:
       
   714 			apiDetail = XMLUtils.DESCRIPTION_KEY_NAME;
       
   715 			break;
       
   716 
       
   717 		default:
       
   718 			throw new IllegalArgumentException(Messages.getString("APIQueryParameters.QueryTypePart1_ErrMsg")  //$NON-NLS-1$
       
   719 					                           + queryType
       
   720 					                           + Messages.getString("APIQueryParameters.QueryTypePart2_ErrMsg") //$NON-NLS-1$
       
   721 					                           );
       
   722 		}
       
   723 		
       
   724 		return apiDetail;
       
   725 	}		
       
   726 	
       
   727 	/*
       
   728 	 * (non-Javadoc)
       
   729 	 * 
       
   730 	 * @see com.nokia.s60tools.apiquery.shared.searchmethod.ISearchMethodExtension#getQueryTypeByAPIDetailNameInDetails(java.lang.String)
       
   731 	 */
       
   732 	public int getQueryTypeByAPIDetailNameInDetails(String queryType) {
       
   733 		int queryInt = -1;
       
   734 		
       
   735 		if(queryType == null){
       
   736 			return queryInt;
       
   737 		}		
       
   738 
       
   739 		if(queryType.equals(MetadataXMLToUIMappingRules.NAME)){
       
   740 			queryInt = APIQueryParameters.QUERY_BY_API_NAME;
       
   741 		}
       
   742 		else if(queryType.equals( MetadataXMLToUIMappingRules.SUBSYSTEM)){
       
   743 			queryInt = APIQueryParameters.QUERY_BY_SUBSYSTEM_NAME;
       
   744 		}
       
   745 		else if(queryType.equals(XMLUtils.DESCRIPTION_DLLS)){
       
   746 			queryInt = APIQueryParameters.QUERY_BY_DLL_NAME;
       
   747 		}
       
   748 		else if(queryType.equals(MetadataXMLToUIMappingRules.LIBS)){
       
   749 			queryInt = APIQueryParameters.QUERY_BY_LIB_NAME;
       
   750 		}
       
   751 		else if(queryType.equals(MetadataXMLToUIMappingRules.HEADERS)){
       
   752 			queryInt = APIQueryParameters.QUERY_BY_HEADER_NAME;
       
   753 		}
       
   754 		else if(queryType.equals(XMLUtils.DESCRIPTION_KEY_NAME)){
       
   755 			queryInt = APIQueryParameters.QUERY_BY_CRPS_KEY_NAME;
       
   756 		}		
       
   757 		
       
   758 		return queryInt;
       
   759 	}
       
   760 
       
   761 	public boolean isAsyncQueryPreferred() {
       
   762 		return false;
       
   763 	}
       
   764 
       
   765 	
       
   766 /**
       
   767  * opens the header file in the workbench
       
   768  */
       
   769 	/*
       
   770 	public int openHeaderFile(String headerName,String source) {
       
   771 		try{
       
   772 		
       
   773 			String temp =source.replace(
       
   774 					"\\", "/");
       
   775 			System.out.println(temp);
       
   776 
       
   777 			temp = temp.substring(0, temp.lastIndexOf("/"))
       
   778 					+ "/inc/" + headerName;
       
   779 			temp = "file://" + temp;
       
   780 			System.out.print("temp" + temp);
       
   781 		
       
   782 		
       
   783 			
       
   784 			OpenFileAction action = new OpenFileAction();
       
   785 			action.openFile(new URI(temp), headerName);
       
   786 		}catch (Exception e) {
       
   787 			return 1;
       
   788 		}
       
   789 		
       
   790 		return 0;
       
   791 	}
       
   792 	*/
       
   793 	
       
   794 	
       
   795 
       
   796 	public boolean serachHeaderLinkEnable() {
       
   797 	
       
   798 		return true;
       
   799 	}
       
   800 
       
   801 	public String[] getHeaderSourceList() {
       
   802 		return	new String[] 
       
   803 				         {"http://s60lxr", "http://developer.symbian.org/xref/oss", "3.2RnDSDK", "pf_5250robot"};			    
       
   804 		
       
   805 		}	
       
   806 	
       
   807 	
       
   808 
       
   809 		public int  openHeaderFile(String headerName, String APIName) {
       
   810 			try{
       
   811 			System.out.println("header" + headerName + "APINAME " +APIName);
       
   812 				
       
   813 		// get the source
       
   814 		String	source =	LocalCacheUIComposite.headerSource;
       
   815 		String url = " ";
       
   816 		boolean isweb = false;
       
   817 		if(source.equalsIgnoreCase("http://s60lxr")){
       
   818 			 url  = "http://s60lxr/search?filestring=%2F"+headerName+"%24&advanced=1&string=";
       
   819 			 isweb = true;			
       
   820 		}
       
   821 		else if(source.equalsIgnoreCase("http://developer.symbian.org/xref/oss"))
       
   822 		{url="http://developer.symbian.org/xref/epl/search?q=&defs=&refs=&path="+headerName+"&hist=&project=%2FMCL";
       
   823 		isweb = true;
       
   824 		}
       
   825 
       
   826 	
       
   827 			
       
   828 			if(isweb)	
       
   829 			{	//open from the browser	
       
   830 				IWorkbench workbench = PlatformUI.getWorkbench();
       
   831 				IWebBrowser browser;
       
   832 
       
   833 				browser = workbench.getBrowserSupport()
       
   834 						.createBrowser(null);
       
   835 							
       
   836 				browser
       
   837 						.openURL(new java.net.URL(url));
       
   838 			}
       
   839 			else
       
   840 			{ //open from the sdk
       
   841 				SDKUtil.headerOpen(source, APIName, headerName);
       
   842 			}
       
   843 			}catch (Exception e) {
       
   844 				e.printStackTrace();
       
   845 			}
       
   846 			
       
   847 			return 0 ;
       
   848 				
       
   849 			}
       
   850 				
       
   851 	 
       
   852 			
       
   853 			
       
   854 		
       
   855 	
       
   856 	
       
   857 	
       
   858 		
       
   859 }