/*
* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of the License "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*
*/


package com.nokia.sdt.series60.viewwizard;

import com.nokia.carbide.cpp.internal.featureTracker.FeatureUseTrackerConsts;
import com.nokia.carbide.cpp.internal.featureTracker.FeatureUseTrackerPlugin;
import com.nokia.carbide.internal.api.templatewizard.ui.IWizardDataPage;
import com.nokia.carbide.internal.api.templatewizard.ui.TemplateWizard;
import com.nokia.carbide.template.engine.ITemplate;
import com.nokia.cpp.internal.api.utils.core.Check;
import com.nokia.cpp.internal.api.utils.core.Logging;
import com.nokia.cpp.internal.api.utils.core.TextUtils;
import com.nokia.cpp.internal.api.utils.ui.UITaskUtils;
import com.nokia.sdt.component.*;
import com.nokia.sdt.component.adapter.CommonAttributes;
import com.nokia.sdt.component.adapter.IAttributes;
import com.nokia.sdt.component.customizer.IComponentCustomizerCommandFactory;
import com.nokia.sdt.component.customizer.ICustomizeComponentCommand;
import com.nokia.sdt.component.event.IEventDescriptor;
import com.nokia.sdt.component.symbian.ComponentProvider;
import com.nokia.sdt.component.symbian.displaymodel.Utilities;
import com.nokia.sdt.datamodel.IDesignerDataModel;
import com.nokia.sdt.datamodel.adapter.*;
import com.nokia.sdt.datamodel.adapter.IEventBinding;
import com.nokia.sdt.datamodel.util.ModelUtils;
import com.nokia.sdt.displaymodel.IDisplayModel;
import com.nokia.sdt.editor.EditorServices;
import com.nokia.sdt.editor.IDesignerDataModelEditor;
import com.nokia.sdt.emf.dm.*;
import com.nokia.sdt.series60.component.Series60ComponentPlugin;
import com.nokia.sdt.sourcegen.*;
import com.nokia.sdt.symbian.S60ComponentAttributes;
import com.nokia.sdt.symbian.dm.*;
import com.nokia.sdt.symbian.ui.UIPlugin;
import com.nokia.sdt.symbian.workspace.ISymbianProjectContext;
import com.nokia.sdt.symbian.workspace.impl.ProjectContextProvider;
import com.nokia.sdt.workspace.*;

import org.eclipse.cdt.core.model.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.wizard.*;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWizard;
import org.eclipse.ui.views.properties.IPropertySource;

import java.lang.reflect.InvocationTargetException;
import java.util.*;

public class ViewWizardManager {
	// store keys
	public static final String PROJECT_NAME_KEY = "PROJECT_NAME"; //$NON-NLS-1$
	public static final String PROJECT_KEY = "PROJECT"; //$NON-NLS-1$
	public static final String APPNAME_KEY = "APPLICATION_NAME"; //$NON-NLS-1$
	public static final String LANGUAGE_ID_KEY = "LANGUAGE_ID"; //$NON-NLS-1$
	public static final String APPUID_KEY = "APP_UID"; //$NON-NLS-1$
	public static final String ROOT_MODEL_KEY = "ROOT_MODEL"; //$NON-NLS-1$
	public static final String COMPONENT_SET_KEY = "COMPONENT_SET"; //$NON-NLS-1$
	public static final String CONTENT_COMPONENT_KEY = "CONTENT_COMPONENT"; //$NON-NLS-1$
	public static final String ROOT_CONTAINER_KEY = "ROOT_CONTAINER"; //$NON-NLS-1$
	public static final String CUSTOMIZER_COMMAND_FACTORY_KEY = "CUSTOMIZER_COMMAND_FACTORY"; //$NON-NLS-1$
	public static final String CONTAINER_BASENAME_KEY = "CONTAINER_BASENAME"; //$NON-NLS-1$
	public static final String HAS_NON_VIEW_SWITCHING_ROOT_MODEL_KEY = "HAS_NON_VIEW_SWITCHING_ROOT_MODEL"; //$NON-NLS-1$
	public static final String WANTS_VIEW_SWITCHING_KEY = "WANTS_VIEW_SWITCHING"; //$NON-NLS-1$
	public static final String CONTAINER_COMPONENT_KEY = "CONTAINER_COMPONENT"; //$NON-NLS-1$
	public static final String TEMP_DATA_MODEL_KEY = "TEMP_DATA_MODEL"; //$NON-NLS-1$
	public static final String VIEW_MODEL_KEY = "VIEW_MODEL"; //$NON-NLS-1$
	public static final String DEFAULT_EVENT_HANDER_BODIES_KEY = "DEFAULT_EVENT_HANDLERS"; //$NON-NLS-1$
	public static final String MMP_FILE_PATH_KEY = "MMP_FILE_PATH"; //$NON-NLS-1$
	
	public static final String MODEL_EXTENSION = ".uidesign"; //$NON-NLS-1$
	// component IDs
	public static final String APPLICATION_COMPONENT_ID = S60ModelUtils.S60_APPLICATION;
	public static final String APPUI_COMPONENT_ID = S60ModelUtils.S60_APPUI;
	public static final String VIEW_APPUI_COMPONENT_ID = S60ModelUtils.S60_VIEW_APPUI;
	public static final String AVKON_VIEW_COMPONENT_ID = S60ModelUtils.S60_AVKON_VIEW;
	public static final String DEFAULT_APPUI_COMPONENT_ID = S60ModelUtils.S60_DEFAULT_APPUI;
	public static final String STATUS_PANE_COMPONENT_ID = S60ModelUtils.S60_STATUSPANE;
	public static final String DOCUMENT_COMPONENT_ID = "com.nokia.sdt.series60.CAknDocument"; //$NON-NLS-1$
	public static final String TEST_COMPONENT_ID = "com.nokia.sdt.series60.WizardTestContainer"; //$NON-NLS-1$
	public static final String STATUS_PANE_TITLE_COMPONENT_ID = "com.nokia.sdt.series60.StatusPaneTitle"; //$NON-NLS-1$
	public static final String STATUS_PANE_CAPTION_COMPONENT_ID = "com.nokia.sdt.series60.StatusPaneCaption"; //$NON-NLS-1$
	public static final String STATUS_PANE_APP_ICON_COMPONENT_ID = "com.nokia.sdt.series60.StatusPaneContextAppIcon"; //$NON-NLS-1$
	public static final String CBA_COMPONENT_ID = "com.nokia.sdt.series60.CBA"; //$NON-NLS-1$
	public static final String CBA_RESTRICTED_COMPONENT_ID = "com.nokia.sdt.series60.CBARestricted"; //$NON-NLS-1$
	public static final String MENUBAR_COMPONENT_ID = "com.nokia.sdt.series60.MenuBar"; //$NON-NLS-1$
	public static final String MENUPANE_COMPONENT_ID = "com.nokia.sdt.series60.MenuPane"; //$NON-NLS-1$
	public static final String MENUITEM_COMPONENT_ID = "com.nokia.sdt.series60.MenuItem"; //$NON-NLS-1$
	public static final String SETTING_ITEM_LIST_COMPONENT_ID = "com.nokia.sdt.series60.CAknSettingItemList"; //$NON-NLS-1$
    // property IDs
	public static final String UID_PROPERTY_NAME = "uid"; //$NON-NLS-1$
	public static final String STATUS_PANE_TITLE_TEXT_PROPERTY_ID = "titleText"; //$NON-NLS-1$
	public static final String CAPTION_PROPERTY_NAME = "caption"; //$NON-NLS-1$
	public static final String STATUS_PANE_CAPTION_SHORT_CAPTION_PROPERTY_NAME = "shortCaption"; //$NON-NLS-1$
	public static final String STATUS_PANE_CAPTION_LONG_CAPTION_PROPERTY_NAME = "longCaption"; //$NON-NLS-1$
	public static final String LONG_CAPTION_PROPERTY_NAME = "shortCaption"; //$NON-NLS-1$
	public static final String CBA_INFO_PROPERTY_NAME = "info"; //$NON-NLS-1$
	public static final String EXITS_APP_PROPERTY_NAME = "exitsApp"; //$NON-NLS-1$
	public static final String INITIAL_FOCUS_PROPERTY_NAME = "initialFocus"; //$NON-NLS-1$
	public static final String LEFT_TEXT_PROPERTY_NAME = "leftText"; //$NON-NLS-1$
	public static final String NAME_PROPERTY_NAME = "name"; //$NON-NLS-1$
	public static final String MENU_ITEM_TEXT_PROPERTY_NAME = "text"; //$NON-NLS-1$
	public static final String DOCUMENT_BASE_PROPERTY_NAME = "documentBase"; //$NON-NLS-1$
	// constants
	private static final String CHANGE_ITEM_HANDLER_NAME = "HandleChangeSelectedSettingItemL";//$NON-NLS-1$
	private static final String SELECTED_EVENT_ID = "selected"; //$NON-NLS-1$

	// template keys
	public static final String TEMPLATE_KEY_APPUI_NAME = "appUiName"; //$NON-NLS-1$
    
	public static final int DEFAULT_HEIGHT = 208;
	public static final int DEFAULT_WIDTH = 176;
	
	// help context ids
	public static final String APPLICATION_DEFINITION_PAGE = "application_properties_page";
	public static final String INITIAL_CONTENT_PAGE = "design_selection_page";
	public static final String CUSTOMIZER_PAGE = "content_variants_page";
	public static final String CONTAINER_SELECTION_PAGE = "container_page";
	
	private ApplicationDefinitionPage appDefinitionPage;
	private InitialContentPage initialContentPage;
	private CustomizerPage customizerPage;
	private ContainerSelectionPage containerSelectionPage;
	private IComponentCustomizerUI customizerUI;
	private ViewWizardPageBase currentPage;
	private boolean extantRootModel;
	private Language appLanguages[];
	
	// not using dialog settings because no need for persistence, 
	// and can't store obj refs in DialogSettings
	private Map dataStore;
	
	private DesignerDataModelProvider dataModelProvider;
	private IComponentProvider componentProvider;
	
	private List pages;
	
	private IWizard wizard;
	private ITemplate template;

	static class DefaultEventBinding {
		private IDesignerDataModel dataModel;
		private IComponentInstance instance;
		private String eventName;
		private String handlerName;
		private String handlerText;

		public DefaultEventBinding(IDesignerDataModel model, IComponentInstance instance,
				String eventName, String handlerName, String handlerText) {
			this.dataModel = model;
			this.instance = instance;
			this.eventName = eventName;
			this.handlerName = handlerName;
			this.handlerText = handlerText;
		}
		
		/** Create the event binding and commit it to the data model */
		public void createEventBinding() {
			IComponentEventDescriptorProvider eventProvider = ModelUtils.getComponentEventDescriptorProvider(instance.getEObject());
			IEventDescriptor descriptor = eventProvider.findEventDescriptor(eventName);
			Command command = dataModel.createAddEventBindingCommand(instance.getEObject(), descriptor, handlerName); 
			Check.checkState(command.canExecute());
			command.execute();
		}
		
		/** Get the bound event */
		public IEventBinding getEventBinding() {
			return instance.findEventBinding(eventName);
		}
		
		/** Write the event handler to the file */
		public void writeEventHandler(IProjectContext pc) throws CoreException {
			IEventBinding binding = getEventBinding();
			Check.checkState(binding != null);
			SourceLocation location = pc.getSourceGenProvider().lookupEventBindingSource(binding);
			Check.checkState(location != null);
			
			ITranslationUnit tunit = (ITranslationUnit)CoreModel.getDefault().create(location.file);
			IBuffer buffer = tunit.getBuffer();
			
			char[] contents = tunit.getContents();

			// replace the TO-DO comment with the new one
			
			// replace the existing line with the handler text
			int endIdx = location.insertOffset;
			int endOffset = location.offset + location.length;
			while (endIdx < endOffset && contents[endIdx] != '\r' && contents[endIdx] != '\n')
				endIdx++;
			
			int currentTextLength = endIdx - location.insertOffset; 
			buffer.replace(location.insertOffset, currentTextLength, handlerText);
			
			buffer.save(null, true);
			buffer.close();
			tunit.close();
		}
	}

	interface IProjectSelectionListener {
		void projectSelectionChanged(IProject project);
	}
	
	private List<IProjectSelectionListener> projectSelectionListeners;
	
	/**
	 * 
	 */
	public ViewWizardManager() {
		dataModelProvider = new DesignerDataModelProvider();
		ComponentSystem cs = ComponentSystem.getComponentSystem();
		try {
			componentProvider = cs.getProvider(ComponentProvider.PROVIDER_ID);
		} 
		catch (CoreException e) {
			Check.reportFailure(Messages.getString("ViewWizard.ComponentProviderError"), e); //$NON-NLS-1$
		}
	}
	
	public Map getDataStore() {
		if (dataStore == null)
			dataStore = new HashMap();

		return dataStore;
	}

	public DesignerDataModelProvider getDataModelProvider() {
		return dataModelProvider;
	}
	
	public IComponentProvider getComponentProvider() {
		return componentProvider;
	}
	
	public void setCurrentPage(ViewWizardPageBase page) {
		currentPage = page;
	}
	
	public ViewWizardPageBase getCurrentPage() {
		return currentPage;
	}

	public List createPages(IWorkbenchWizard wizard, IWorkbench workbench, IStructuredSelection selectedResources) {
		this.wizard = wizard;
		if (pages == null) {
			pages = new ArrayList();
			appDefinitionPage = new ApplicationDefinitionPage(selectedResources, this);
			pages.add(appDefinitionPage);
			initialContentPage = new InitialContentPage(this);
			pages.add(initialContentPage);
			customizerPage = new CustomizerPage(this);
			pages.add(customizerPage);
			containerSelectionPage = new ContainerSelectionPage(this);
			pages.add(containerSelectionPage);
		}
		return pages;
	}
	
	public IWizardDataPage[] createAdditionalPages(IWorkbenchWizard wizard, IWorkbench workbench, IStructuredSelection selection) {
		createPages(wizard, workbench, selection);
		return getPages();
	}
	
	public IWizardDataPage[] getPages() {
		Check.checkContract(pages != null);
		return (IWizardDataPage[]) pages.toArray(new IWizardDataPage[pages.size()]);
	}
	
	private void createRootModelFromWizardData(ISymbianProjectContext symbianProjectContext, boolean isLegacy) throws Exception {
		IProject project = (IProject) getDataStore().get(PROJECT_KEY);
		Check.checkContract(project != null);
		IDesignerDataModel dataModel = getDataModelProvider().createTemporary();
		dataModel.setComponentSet(getComponentSet());
		
		// set the language in the string bundle
		IDesignerData data = ((DesignerDataModel) dataModel).getDesignerData();
		Integer languageID = (Integer) getDataStore().get(LANGUAGE_ID_KEY);
		Language language = new Language(languageID.intValue());
		data.getStringBundle().setDefaultLanguage(language);
		symbianProjectContext.setCurrentLanguage(language);
		
		// set properties
		String appName = (String) getDataStore().get(APPNAME_KEY);
		Check.checkContract(appName != null);
		dataModel.setProperty(DesignerDataModel.ROOT_APPLICATION_NAME, appName);
		WizardUtils.addSourceGenPropertiesFromTemplate(dataModel, template, isLegacy);
		
		IComponent applicationComponent = 
			getComponentSet().lookupComponent(APPLICATION_COMPONENT_ID);
        String appInstanceName = appName + "Application"; //$NON-NLS-1$
        EObject application = WizardUtils.addRootInstance(dataModel, applicationComponent, appInstanceName, "C" + appInstanceName); //$NON-NLS-1$
		IPropertySource propertySource = WizardUtils.getProperties(application);
		String appUID = (String) getDataStore().get(APPUID_KEY);
		if (appUID == null)
			appUID = getAppUIDFromTemplate();
		propertySource.setPropertyValue(UID_PROPERTY_NAME, appUID);
		propertySource.setPropertyValue(DOCUMENT_BASE_PROPERTY_NAME, appName);
		
		IComponent documentComponent = getComponentSet().lookupComponent(DOCUMENT_COMPONENT_ID);
        String documentInstanceName = appName + "Document"; //$NON-NLS-1$
        EObject document = WizardUtils.addChildObject(dataModel, documentComponent, application, 
										documentInstanceName, "C" + documentInstanceName, IDesignerDataModel.AT_END); //$NON-NLS-1$
		IComponent appuiComponent = getAppUiComponent();
		String appuiName = appName + "AppUi"; //$NON-NLS-1$
		
		EObject appui = WizardUtils.addChildObject(dataModel, appuiComponent, document, 
										appuiName, "C" + appuiName, IDesignerDataModel.AT_END); //$NON-NLS-1$
//		propertySource = WizardUtils.getProperties(appui);
		if (template != null)
			template.getTemplateValues().put(TEMPLATE_KEY_APPUI_NAME, appuiName);
		dataModel.setProperty(DesignerDataModel.ROOT_CONTAINER_OVERRIDE_ID, appuiName);
		IDisplayModel displayModel = dataModel.getDisplayModelForRootContainer(appui);
		addRootStatusAndCBA(dataModel, appui, appName, null, false);

		WizardUtils.addDefaultBoundsToInstance(appui, displayModel, DEFAULT_WIDTH, DEFAULT_HEIGHT);
		
		// only add a menubar if not view-switching
		if (!isViewSwitching()) {
			EObject nonLayoutRoot = displayModel.getNonLayoutRoot();
			addOptionsMenu(dataModel, nonLayoutRoot, nonLayoutRoot);
		}

		getDataStore().put(ROOT_MODEL_KEY, dataModel);
	}
	
	private String getAppUIDFromTemplate() {
		Check.checkState(template != null);
		String appUID = (String) template.getTemplateValues().get("uid3"); //$NON-NLS-1$
		Check.checkState(appUID != null);
		return appUID.toLowerCase();
	}

	private void createViewModelFromWizardData(Language language) throws Exception {
		IProject project = (IProject) getDataStore().get(PROJECT_KEY);
		Check.checkContract(project != null);
		DesignerDataModel dataModel = (DesignerDataModel) getDataModelProvider().createTemporary();
		dataModel.setComponentSet(getComponentSet());
		
		// ensure the view model's string bundle is synched with the application and the
		// current language is set
		ILocalizedStringBundle stringBundle = dataModel.getDesignerData().getStringBundle();
		if (appLanguages != null) {
			for (Language l : appLanguages) {
				stringBundle.addLocalizedStringTable(l);
			}
		}
		stringBundle.setDefaultLanguage(language);

		// set properties
		IDesignerDataModel rootModel = (IDesignerDataModel) getDataStore().get(ROOT_MODEL_KEY);
		WizardUtils.addSourceGenPropertiesFromModel(dataModel, rootModel);

		boolean viewSwitching = isViewSwitching();
		IComponent rootComponent = getViewRootComponent(viewSwitching);
		String rootClassName = getViewRootClassName(viewSwitching);
		EObject rootInstance = WizardUtils.addRootInstance(dataModel, rootComponent, getViewRootName(viewSwitching), rootClassName);
		IDisplayModel displayModel = dataModel.getDisplayModelForRootContainer(rootInstance);
		
		IComponent containerComponent = (IComponent) getDataStore().get(CONTAINER_COMPONENT_KEY);
		String containerName = (String) getDataStore().get(CONTAINER_BASENAME_KEY);
		String containerClassName = "C" + TextUtils.titleCase(containerName); //$NON-NLS-1$
		EObject container = 
			WizardUtils.addChildObject(dataModel, containerComponent, rootInstance, 
											containerName, containerClassName, IDesignerDataModel.AT_END);

		boolean restrictedCBA = useRestrictedCBA(container);
		if (isViewSwitching()) {
			addViewStatusAndCBA(dataModel, rootInstance, 
					getViewModelName(), 
					getDefaultCBAValue(rootInstance, container), restrictedCBA);
		} 
		else {
			// for non-view-switching, only add a cba if container wants it in parent
			if (Utilities.hasBooleanAttribute(container, S60ComponentAttributes.USES_CBA_IN_PARENT)) {
				addCBA(dataModel, rootInstance, getDefaultCBAValue(rootInstance, container), restrictedCBA);
			}
		}
		
//		if (!hasViews(project))
//			setExitsApp(container);
		
		WizardUtils.addDefaultBoundsToInstance(rootInstance, displayModel, DEFAULT_WIDTH, DEFAULT_HEIGHT);
		
		// only add a menubar if view-switching -or- if the container is the non-layout root
		// don't add options menu if the container has a builtin options menu
		boolean hasBuiltInMenu = 
			Utilities.hasBooleanAttribute(container, S60ComponentAttributes.HAS_BUILTIN_OPTIONS_MENU);
		boolean addOptionsMenu = isViewSwitching() && !hasBuiltInMenu; 
		EObject nonLayoutRoot = displayModel.getNonLayoutRoot();
		if (!addOptionsMenu && !hasBuiltInMenu)
			addOptionsMenu = Utilities.getStringAttribute(nonLayoutRoot, 
					S60ComponentAttributes.OPTIONS_MENU_PROPERTY_NAME) != null;

		if (addOptionsMenu) {
			EObject optionsMenu = addOptionsMenu(dataModel, nonLayoutRoot, nonLayoutRoot);
			if (ModelUtils.isInstanceOf(container, SETTING_ITEM_LIST_COMPONENT_ID)) {
				// add default items
				populateSettingItemListOptionsMenu(dataModel, container, optionsMenu);
			}
		}
		
		
		IComponent contentComponent = (IComponent) getDataStore().get(CONTENT_COMPONENT_KEY);
		if ((contentComponent != null) && 
				(!contentComponent.getId().equals(containerComponent.getId()))) {
			EObject contentObject = WizardUtils.addChildObject(dataModel, contentComponent, container, 
																	null, null, IDesignerDataModel.AT_END);
		
			IComponentCustomizerCommandFactory customizerCommandFactory = 
				(IComponentCustomizerCommandFactory) getDataStore().get(CUSTOMIZER_COMMAND_FACTORY_KEY);
			if (customizerCommandFactory != null) {
				ICustomizeComponentCommand command = 
					customizerCommandFactory.createCustomizeComponentCommand(contentObject);
				Check.checkState(command != null);
				if (command.canExecute()) {
					String error = command.execute();
					if (error != null)
						Check.reportFailure(error, new Exception());
				}
			}
			
			// Set initialFocus property if the container has one. This
			// assumes every content component is derived from CCoeControl.
			// If not, an additional check is needed here.
			IPropertySource containerPS = ModelUtils.getPropertySource(container);
			if (ModelUtils.hasProperty(containerPS, INITIAL_FOCUS_PROPERTY_NAME)) {
				IPropertySource contentPS = ModelUtils.getPropertySource(contentObject);
				containerPS.setPropertyValue(INITIAL_FOCUS_PROPERTY_NAME, contentPS.getPropertyValue(NAME_PROPERTY_NAME));
			}
		}
		
		getDataStore().put(VIEW_MODEL_KEY, dataModel);
	}

//	private boolean hasViews(IProject project) {
//		WorkspaceContext wc = WorkspaceContext.getContext();
//		final IProjectContext pc = wc.getContextForProject(project);
//		Check.checkContract(pc != null);
//		IDesignerDataModelSpecifier[] modelSpecifiers = pc.getModelSpecifiers();
//		for (int i = 0; i < modelSpecifiers.length; i++) {
//			IDesignerDataModelSpecifier specifier = modelSpecifiers[i];
//			ISymbianDataModelSpecifier symbianSpecifier = 
//				(ISymbianDataModelSpecifier) specifier.getAdapter(ISymbianDataModelSpecifier.class);
//			if (!symbianSpecifier.isRoot())
//				return true;
//		}
//		
//		return false;
//	}
//
//	private void setExitsApp(EObject container) {
//		IPropertySource properties = Utilities.getPropertySource(container);
//		properties.setPropertyValue(EXITS_APP_PROPERTY_NAME, "true"); //$NON-NLS-1$
//	}

	private String getDefaultCBAValue(EObject rootInstance, EObject containerInstance) {
		// if the container specifies the CBA for the parent, then look for the default in the container
		// else look for the default in the root instance
		EObject instanceWithDefault = 
			Utilities.hasBooleanAttribute(containerInstance, S60ComponentAttributes.USES_CBA_IN_PARENT) ?
					containerInstance : rootInstance;
		
		return 
			Utilities.getStringAttribute(instanceWithDefault, S60ComponentAttributes.DEFAULT_CBA_VALUE);
	}
	
	private void addRootStatusAndCBA(IDesignerDataModel dataModel, EObject parent, String statusTitle, 
																String defaultCBAValue, boolean restrictedCBA) {
		addCBA(dataModel, parent, defaultCBAValue, restrictedCBA);
		IComponent statusPaneComponent = getComponentSet().lookupComponent(STATUS_PANE_COMPONENT_ID);
		EObject statusPane = WizardUtils.addChildObject(dataModel, statusPaneComponent, parent, 
												"statusPane", null, IDesignerDataModel.IN_FRONT); //$NON-NLS-1$
		if (statusPane != null) {
			if (statusTitle != null) {
			    IComponent captionComponent = getComponentSet().lookupComponent(STATUS_PANE_CAPTION_COMPONENT_ID);
		        EObject caption = WizardUtils.addChildObject(dataModel, captionComponent, statusPane, 
		        									"caption", null, IDesignerDataModel.IN_FRONT); //$NON-NLS-1$
				IPropertySource ps = WizardUtils.getProperties(caption);
				if (ps != null) {
					ps.setPropertyValue(STATUS_PANE_CAPTION_LONG_CAPTION_PROPERTY_NAME, statusTitle); //$NON-NLS-1$
					ps.setPropertyValue(STATUS_PANE_CAPTION_SHORT_CAPTION_PROPERTY_NAME, statusTitle); //$NON-NLS-1$
				}
			}

			// add the application icon if it is required
			// (read: not user removable)
		    IComponent appIconComponent = getComponentSet().lookupComponent(STATUS_PANE_APP_ICON_COMPONENT_ID);
		    if (appIconComponent != null) {
		    	IAttributes attrs = (IAttributes) appIconComponent.getAdapter(IAttributes.class);
		    	if (attrs != null && attrs.getBooleanAttribute(CommonAttributes.IS_NOT_USER_REMOVABLE, false)) {
		    		/*EObject appIcon =*/ WizardUtils.addChildObject(dataModel, appIconComponent, statusPane, 
		    				"appIcon", null, IDesignerDataModel.AT_END); //$NON-NLS-1$
		    	}
		    }
		}
	}

	private void addViewStatusAndCBA(IDesignerDataModel dataModel, EObject parent, String statusTitle, 
																String defaultCBAValue, boolean restrictedCBA) {
		addCBA(dataModel, parent, defaultCBAValue, restrictedCBA);
		IComponent statusPaneComponent = getComponentSet().lookupComponent(STATUS_PANE_COMPONENT_ID);
		EObject statusPane = WizardUtils.addChildObject(dataModel, statusPaneComponent, parent, 
												"statusPane", null, IDesignerDataModel.IN_FRONT); //$NON-NLS-1$
		if (statusPane != null && statusTitle != null) {
		    IComponent titleComponent = getComponentSet().lookupComponent(STATUS_PANE_TITLE_COMPONENT_ID);
            EObject title = WizardUtils.addChildObject(dataModel, titleComponent, statusPane, 
            									"title", null, IDesignerDataModel.IN_FRONT); //$NON-NLS-1$
			IPropertySource ps = WizardUtils.getProperties(title);
			if (ps != null) {
				ps.setPropertyValue(STATUS_PANE_TITLE_TEXT_PROPERTY_ID, statusTitle); //$NON-NLS-1$
			}
		}
	}
	
	private void addCBA(IDesignerDataModel dataModel, EObject parent, String defaultValue, boolean restricted) {
		String cbaId = restricted ? CBA_RESTRICTED_COMPONENT_ID : CBA_COMPONENT_ID;
		IComponent cba = getComponentSet().lookupComponent(cbaId);
		EObject cbaInstance = WizardUtils.addChildObject(dataModel, cba, parent, 
												"controlPane", null, IDesignerDataModel.IN_FRONT); //$NON-NLS-1$
		if (defaultValue != null) {
			IPropertySource cbaProperties = Utilities.getPropertySource(cbaInstance);
			cbaProperties.setPropertyValue(CBA_INFO_PROPERTY_NAME, defaultValue);
		}
	}
	
	private boolean useRestrictedCBA(EObject container) {
		return Utilities.hasBooleanAttribute(container, S60ComponentAttributes.USE_RESTRICTED_CBA);
	}
	
	private EObject addOptionsMenu(IDesignerDataModel dataModel, EObject parent, EObject referenceOwner) {
		IComponent menuBarComponent = getComponentSet().lookupComponent(MENUBAR_COMPONENT_ID);
		String optionsMenuName = "optionsMenu"; //$NON-NLS-1$
		EObject optionsMenu = WizardUtils.addChildObject(dataModel, menuBarComponent, parent, 
											optionsMenuName, null, IDesignerDataModel.AT_END);
		IPropertySource propertySource = WizardUtils.getProperties(referenceOwner);
		String optionsMenuPropertyName = Utilities.getStringAttribute(referenceOwner,
				S60ComponentAttributes.OPTIONS_MENU_PROPERTY_NAME);
		propertySource.setPropertyValue(optionsMenuPropertyName, optionsMenuName);
		return optionsMenu;
	}

	/**
	 * Add the "Change" item to a setting item list's view's Options menu.  
	 * The setting item has a ready-made routine, ChangeSelectedItemL(), for this.
	 * It can leave, which is stupid, but oh well.
	 */
	private void populateSettingItemListOptionsMenu(IDesignerDataModel dataModel, EObject settingsList, EObject optionsMenu) {
		IComponent menuPaneComponent = getComponentSet().lookupComponent(MENUPANE_COMPONENT_ID);
		EObject optionsPane = WizardUtils.addChildObject(dataModel, menuPaneComponent, optionsMenu, 
				null, null, IDesignerDataModel.AT_END);
		IComponent menuItemComponent = getComponentSet().lookupComponent(MENUITEM_COMPONENT_ID);
		EObject changeItem = WizardUtils.addChildObject(dataModel, menuItemComponent, optionsPane, 
				null, null, IDesignerDataModel.AT_END);
		IPropertySource propertySource = WizardUtils.getProperties(changeItem);
		propertySource.setPropertyValue(MENU_ITEM_TEXT_PROPERTY_NAME, "Change"); //$NON-NLS-1$
		
		// wire up the event handler and set its body for later insertion
		DefaultEventBinding binding = new DefaultEventBinding(
				dataModel, ModelUtils.getComponentInstance(changeItem),
				SELECTED_EVENT_ID, CHANGE_ITEM_HANDLER_NAME,
				// This makes assumptions abouts the way instance member names are constructed
				"i" + TextUtils.titleCase(ModelUtils.getComponentInstance(settingsList).getName()) 
				+ "->ChangeSelectedItemL();"); //$NON-NLS-1$
		binding.createEventBinding();
		
		getDefaultEventHandlerBodies().add(binding);
	}
	
	/**
	 * Get list of default event bindings
	 * @return
	 */
	private List getDefaultEventHandlerBodies() {
		Map store = getDataStore();
		List<DefaultEventBinding> bindings = (List<DefaultEventBinding>) store.get(DEFAULT_EVENT_HANDER_BODIES_KEY);
		if (bindings == null) {
			bindings = new ArrayList<DefaultEventBinding>();
			store.put(DEFAULT_EVENT_HANDER_BODIES_KEY, bindings);
		}
		return bindings;
	}
	
	/**
	 * Edit source code, writing the bodies of selected event handlers
	 * with our code.
	 * @param pc 
	 */
	private void writeDefaultEventHandlerBodies(IProjectContext pc) {
		if (pc.getSourceGenProvider() == null)
			return;
		List<DefaultEventBinding> bindings = getDefaultEventHandlerBodies();
		for (Iterator iter = bindings.iterator(); iter.hasNext();) {
			DefaultEventBinding bindingInfo = (DefaultEventBinding) iter.next();
			try {
				bindingInfo.writeEventHandler(pc);
			} catch (CoreException e) {
				IStatus status = Logging.newStatus(Series60ComponentPlugin.getDefault(), e);
				Logging.showErrorDialog(Messages.getString("ViewWizardManager.ErrorWritingEventHandlerTitle"), Messages.getString("ViewWizardManager.ErrorWritingEventHandlerMessage"), status); //$NON-NLS-1$ //$NON-NLS-2$
			}
		}
	}

	private boolean isViewSwitching() {
		Boolean value = (Boolean) getDataStore().get(WANTS_VIEW_SWITCHING_KEY);
		return (value != null) && value.booleanValue();
	}
	
	private IComponent getAppUiComponent() {
		return isViewSwitching() ?
			getComponentSet().lookupComponent(VIEW_APPUI_COMPONENT_ID) :
			getComponentSet().lookupComponent(APPUI_COMPONENT_ID);
	}

	private IComponent getViewRootComponent(boolean viewSwitching) {
		return viewSwitching ?
			getComponentSet().lookupComponent(AVKON_VIEW_COMPONENT_ID) :
			getComponentSet().lookupComponent(DEFAULT_APPUI_COMPONENT_ID);
	}
	
	private String getViewRootName(boolean viewSwitching) {
		if (viewSwitching) {
			return S60ModelUtils.getAvkonViewName((String) getDataStore().get(CONTAINER_BASENAME_KEY));
		}
		else {
			IDesignerDataModel rootModel = (IDesignerDataModel) getDataStore().get(ROOT_MODEL_KEY);
			EObject rootContainer = rootModel.getRootContainers()[0];
			return WizardUtils.getComponentInstance(rootContainer).getName();
		}
	}

	private String getViewRootClassName(boolean viewSwitching) {
		if (viewSwitching) {
			return "C" + getViewRootName(viewSwitching); //$NON-NLS-1$
		}
		else {
			IDesignerDataModel rootModel = (IDesignerDataModel) getDataStore().get(ROOT_MODEL_KEY);
			EObject rootContainer = rootModel.getRootContainers()[0];
			return (String) WizardUtils.getProperties(rootContainer).getPropertyValue(
																	WizardUtils.CLASS_NAME_PROPERTY_ID);
		}
	}
	
	private void addDesignReferenceToRootModel(IDesignerDataModel rootModel, IDesignerDataModelSpecifier viewDesignSpecifier) {
		Command command = SymbianModelUtils.addViewReference(rootModel, viewDesignSpecifier);
		if (command.canExecute())
			command.execute();
		
		command = S60ModelUtils.ensureInitialView(rootModel);
		if (command != null && command.canExecute()) {
			command.execute();
		}
	}

	// TODO: fix this -- it's intended to prevent two data models from being
    // generated at the same time, but it seems to conflict with the creation
    // of resources by sourcegen.
    static class DataModelConflictingRule implements ISchedulingRule {

        /* (non-Javadoc)
         * @see org.eclipse.core.runtime.jobs.ISchedulingRule#contains(org.eclipse.core.runtime.jobs.ISchedulingRule)
         */
        public boolean contains(ISchedulingRule rule) {
            return rule == this;
        }

        /* (non-Javadoc)
         * @see org.eclipse.core.runtime.jobs.ISchedulingRule#isConflicting(org.eclipse.core.runtime.jobs.ISchedulingRule)
         */
        public boolean isConflicting(ISchedulingRule rule) {
            return rule instanceof DataModelConflictingRule;
        }
        
    }
    
	public void generateModels(boolean minimalRootModel) {
		currentPage.leavingPage(null);
		ensureProjectExists();

		final IProject project = (IProject) getDataStore().get(PROJECT_KEY);
		Check.checkContract(project != null);
		ProjectContextProvider.beginProjectCreation(project);
		final WorkspaceContext wc = WorkspaceContext.getContext();
		final IProjectContext pc = wc.getContextForProject(project);
		Check.checkContract(pc != null);
		ProjectContextProvider.endProjectCreation(project);
		
		ISymbianProjectContext spc = (ISymbianProjectContext) pc.getAdapter(ISymbianProjectContext.class);
		
        if (!extantRootModel) {
    		try {
    		    createRootModelFromWizardData(spc, minimalRootModel);
    		} 
    		catch (Throwable t) {
    			Check.reportFailure(Messages.getString("ViewWizard.RootModelCreateError"), t); //$NON-NLS-1$
    		}
        }
        
		try {
			createViewModelFromWizardData(spc.getCurrentLanguage());
		} 
		catch (Throwable t) {
			Check.reportFailure(Messages.getString("ViewWizard.ViewModelCreateError"), t); //$NON-NLS-1$
		}
	}
	
	/**
	 * Save models and handle the delicate ordering of saving and sourcegen.
	 * <p>
	 * On initial project creation (newRootModel==true), we must write the root and view model
	 * files to disk and refresh the project context without generating source, so that
	 * both models are registered when sourcegen runs.
	 * <p>
	 * When creating a new view, the case is similar; we must register models before
	 * updating source.
	 *   
	 * @param newRootModel
	 * @param srcGenRoot true: generate source for root, false: don't
	 * @param monitor the progress monitor
	 */
	public void saveModels(boolean newRootModel, boolean srcGenRoot, IProgressMonitor monitor) {
		final IProject project = (IProject) getDataStore().get(PROJECT_KEY);
		Check.checkContract(project != null);
		final WorkspaceContext wc = WorkspaceContext.getContext();
		final IProjectContext pc = wc.getContextForProject(project);
		Check.checkContract(pc != null);
		ISymbianProjectContext spc = (ISymbianProjectContext) pc.getAdapter(ISymbianProjectContext.class);

		ISourceGenProvider sourceGenProvider = pc.getSourceGenProvider();

		// get root
		IDesignerDataModel rootModel = null;
		rootModel = (IDesignerDataModel) getDataStore().get(ROOT_MODEL_KEY);
		
		// turn off resource listening
		IDesignerDataModelEditor rootEditor = EditorServices.findEditorForModel(rootModel.getModelSpecifier());
		if (rootEditor != null)
			rootEditor.setListenToResourceChanges(false);

		IDesignerDataModelSpecifier viewSpecifier = createModelSpecifier(project, spc);

		// save view model without generating source
		IDesignerDataModel viewModel = null;
		viewModel = saveViewModel(project, wc, pc, rootModel, viewSpecifier, monitor);

		// get or create specifier for root 
		IDesignerDataModelSpecifier rootModelSpecifier = null;
		if (newRootModel)
			rootModelSpecifier = spc.createNewRootModelSpecifier();
		else
			rootModelSpecifier = rootModel.getModelSpecifier();
		Check.checkState(rootModelSpecifier != null);

		// register view design reference in root model
		addDesignReferenceToRootModel(rootModel, viewSpecifier);

		// save root without generating source
		boolean rootGeneratedSource = WizardUtils.toggleSourceGeneration(rootModel, false);
		rootModel = saveRootModel(project, wc, rootModelSpecifier, monitor);
		WizardUtils.toggleSourceGeneration(rootModel, rootGeneratedSource);

		// let project context detect the model changes
		pc.refresh(null);
		
		// ensure they're found...
		Check.checkState(pc.findSpecifierForPath(rootModelSpecifier.getPrimaryResourcePath()) != null);
		Check.checkState(pc.findSpecifierForPath(viewSpecifier.getPrimaryResourcePath()) != null);

		// now save again with sourcegen enabled
		
		// save view first, so root can access its RootAppUi resources
		WizardUtils.setupSourceGeneration(sourceGenProvider, viewModel, viewSpecifier);
		saveViewModel(project, wc, pc, rootModel, viewSpecifier, monitor);		

		// now save root
		if (srcGenRoot) {
			WizardUtils.setupSourceGeneration(sourceGenProvider, rootModel, rootModel.getModelSpecifier());
			saveRootModel(project, wc, rootModelSpecifier, monitor);
		}
		
		// after all that, add default event handler code
		writeDefaultEventHandlerBodies(pc);

		// re-enable resource listening
		if (rootEditor != null)
			rootEditor.setListenToResourceChanges(true);

		// don't show editor opening progress, since wizard provides progress
		EditorServices.setStifleProgress(true);				
		try {
			try {
				if (newRootModel)
					rootModel.getModelSpecifier().openInEditor();
			} catch (CoreException e) {
				Check.reportFailure(Messages.getString("ViewWizard.RootModelOpenError"), e); //$NON-NLS-1$
			}
	
			// reload root editor if open
			if (rootEditor != null)
				rootEditor.reload();
	
			try {
				viewModel.getModelSpecifier().openInEditor();
			} catch (CoreException e) {
				Check.reportFailure(Messages.getString("ViewWizard.ViewModelOpenError"), e); //$NON-NLS-1$
			}
		} finally {
			EditorServices.setStifleProgress(false);				
		}
	}

	private IDesignerDataModel saveRootModel(final IProject project, final WorkspaceContext wc, 
			IDesignerDataModelSpecifier rootSpecifier, IProgressMonitor monitor) {
		IDesignerDataModel rootModel;
		
		rootModel = (IDesignerDataModel) getDataStore().get(ROOT_MODEL_KEY);

		try {
			rootModel.saveModelAs(rootSpecifier, monitor);
			wc.projectChanged(project);
	    } 
		catch (Exception e) {
	        Check.reportFailure(Messages.getString("ViewWizard.RootModelSaveError"), e); //$NON-NLS-1$
	    }

		return rootModel;
	}

	/**
	 * Get the name used to name the *.uidesign file.
	 * @return filename base
	 */
	private String getViewModelName() {
		String containerName = (String) getDataStore().get(CONTAINER_BASENAME_KEY);
		Check.checkContract(containerName != null);
		return containerName;
	}
	
	private IDesignerDataModel saveViewModel(final IProject project, final WorkspaceContext wc, final IProjectContext pc,  
			IDesignerDataModel rootModel, IDesignerDataModelSpecifier viewSpecifier, IProgressMonitor monitor) {
		final IDesignerDataModel viewModel = (IDesignerDataModel) getDataStore().get(VIEW_MODEL_KEY);

	    try {
	        pc.refresh(null);
	        monitor.beginTask(Messages.getString("ViewWizard.SavingViewDataModel"), 2 /* view, then root */); //$NON-NLS-1$
			viewModel.saveModelAs(viewSpecifier, new SubProgressMonitor(monitor, 1));
			monitor.worked(1);
			wc.projectChanged(pc.getProject());
		} 
		catch (Exception e) {
			Check.reportFailure(Messages.getString("ViewWizard.ViewModelSaveError"), e); //$NON-NLS-1$
		}
				
		return viewModel;
	}

	/**
	 * @param project
	 * @param spc
	 * @return
	 */
	private IDesignerDataModelSpecifier createModelSpecifier(final IProject project, ISymbianProjectContext spc) {
		String viewFileName = getViewModelName() + MODEL_EXTENSION;
		IFile viewFile = project.getFile(viewFileName);
		final IDesignerDataModelSpecifier viewSpecifier = spc.createNewModelSpecifier(viewFile);
		return viewSpecifier;
	}
	
	private void ensureProjectExists() {
		IProject project = null;
		if (!getDataStore().containsKey(PROJECT_KEY)) {
			String projectName = (String) getDataStore().get(PROJECT_NAME_KEY);
			Check.checkContract(projectName != null);
			IWorkspace workspace = ResourcesPlugin.getWorkspace();
			IWorkspaceRoot root = workspace.getRoot();
			project = root.getProject(projectName);
			Check.checkContract(project != null);
			getDataStore().put(PROJECT_KEY, project);
		}
		else
			project = (IProject) getDataStore().get(PROJECT_KEY);
		
//		SymbianProjectUtils.addUIDesignerProjectNatureToProject(project);
	}
	
	public void disposePages() {
		for (Iterator<ViewWizardPageBase> iter = pages.iterator(); iter.hasNext();) {
			iter.next().dispose();
		}
	}

	public void disposeModels(boolean all) {
		disposeStoredModel(TEMP_DATA_MODEL_KEY);
		if (all || !extantRootModel) {
			disposeStoredModel(ROOT_MODEL_KEY);
		}
		disposeStoredModel(VIEW_MODEL_KEY);
	}
	
	public void disposeStoredModel(String modelKey) {
		IDesignerDataModel dataModel = 
			(IDesignerDataModel) getDataStore().get(modelKey);
		if (dataModel != null) {
			dataModel.dispose();
			getDataStore().remove(modelKey);
		}
	}

	public IDesignerDataModel createEmptyViewModel() throws Exception {
		IDesignerDataModel dataModel = getDataModelProvider().createTemporary();
		dataModel.setComponentSet(getComponentSet());

		return dataModel;
	}
	
	public IComponentSet getComponentSet() {
		return (IComponentSet) getDataStore().get(COMPONENT_SET_KEY);
	}
	
	public boolean isLastPage(IWizardPage page) {
		return page.equals(containerSelectionPage);
	}
	
	public IWizardPage getNextPage(IWizardPage page) {
		if (page.equals(appDefinitionPage))
			return initialContentPage;
		
		if (page.equals(initialContentPage)) {
			if (customizerUI != null)
				return customizerPage;
			else
				return containerSelectionPage;
		}
		
		if (page.equals(customizerPage))
			return containerSelectionPage;
		
		return page.getWizard().getNextPage(page);
	}

	public IWizardPage getPreviousPage(IWizardPage page) {
		if (page.equals(appDefinitionPage))
			return page.getPreviousPage();
		
		if (page.equals(containerSelectionPage)) {
			if (customizerUI != null)
				return customizerPage;
			else
				return initialContentPage;
		}
		
		if (page.equals(customizerPage))
			return initialContentPage;
		
		if (page.equals(initialContentPage))
			return appDefinitionPage;
		
		return page.getWizard().getPreviousPage(page);
	}
	
	public IWizardPage getPage(String pageName) {
		IWizardPage page = wizard.getPage(pageName);
		if ((page == null) && (wizard instanceof TemplateWizard)) {
			WizardSelectionPage wizardSelectionPage = ((TemplateWizard) wizard).getChooseTemplatePage();
			IWizardNode selectedNode = wizardSelectionPage.getSelectedNode();
			IWizard nodeWizard = selectedNode.getWizard();
			page = nodeWizard.getPage(pageName);
		}
		
		return page;
	}

	public void setCustomizerUI(IComponentCustomizerUI customizerUI) {
		this.customizerUI = customizerUI;
		customizerPage.setCustomizerUI(customizerUI);
	}

	public boolean checkProjectWizard(boolean updateDataStore) {
		IWizardPage page = getPage("New Project Page"); //$NON-NLS-1$
		String projectName = null;
		if (page instanceof IWizardDataPage) {
			projectName = (String) ((IWizardDataPage) page).getPageValues().get("projectName"); //$NON-NLS-1$
			if ((projectName != null) && updateDataStore)
				getDataStore().put(PROJECT_NAME_KEY, projectName);
		}
		return projectName != null;
	}

	public void setTemplate(ITemplate template) {
		this.template = template;
	}

	public IWizard getWizard() {
		return wizard;
	}
	
	public void addProjectSelectionListener(IProjectSelectionListener listener) {
		if (projectSelectionListeners == null)
			projectSelectionListeners = new ArrayList<IProjectSelectionListener>();
		
		projectSelectionListeners.add(listener);
	}
	
	void fireProjectSelectionChanged(IProject project) {
		if (projectSelectionListeners == null)
			return;
		
		for (Iterator<IProjectSelectionListener> iter = projectSelectionListeners.iterator(); iter.hasNext();) {
			iter.next().projectSelectionChanged(project);
		}
	}

	public void setExtantRootModel(boolean hasRootModel) {
		extantRootModel = hasRootModel;
	}
	
	public void setApplicationLanguages(Language[] appLanguages) {
		this.appLanguages = appLanguages;
	}

	/**
	 * Find collisions between existing sources and those generated by a new model.
	 * @return list of project-relative paths
	 */
	public List<IPath> getSourceCollisions() {
		WorkspaceContext wc = WorkspaceContext.getContext();
		final IProject project = (IProject) getDataStore().get(PROJECT_KEY);
		final IProjectContext pc = wc.getContextForProject(project);
		Check.checkContract(pc != null);
		final ISymbianProjectContext spc = (ISymbianProjectContext) pc.getAdapter(ISymbianProjectContext.class);
		final IDesignerDataModelSpecifier modelSpecifier = createModelSpecifier(project, spc);

		// create a separate provider so we don't disturb the existing one
		ISourceGenProvider provider;
		try {
			provider = SourceGenUtils.loadSourceGenProvider(SymbianModelUtils.SOURCEGEN_PROVIDER_ID, project);
		} catch (CoreException e) {
			UIPlugin.log(e);
			return Collections.EMPTY_LIST;
		}
			//pc.getSourceGenProvider();
		Check.checkContract(provider != null);

		final List<IPath> collisions = new ArrayList<IPath>();
		
		// check view model (use runnable to get busy notification)
		IDesignerDataModel model = (IDesignerDataModel) getDataStore().get(VIEW_MODEL_KEY);
		final ISourceGenSession session = SymbianModelUtils.createSourceGenSession(provider, model, modelSpecifier);
		UITaskUtils.runImmediately(new IRunnableWithProgress() {
			public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
				List<IPath> sources = session.scanForGeneratedSources(monitor);
				filterCollisions(collisions, project, sources);
			}
		});
		session.dispose();
		provider.dispose();
		
		return collisions; 
	}

	/**
	 * Check whether any of the files in sources exists in project.
	 * @param project
	 * @param sources
	 * @return true: collisions found
	 */
	private void filterCollisions(List<IPath> collisions, IProject project, List<IPath> sources) {
		for (Iterator iter = sources.iterator(); iter.hasNext();) {
			IPath path = (IPath) iter.next();
			IResource rsrc = project.findMember(path);
			if (rsrc != null && rsrc.exists())
				collisions.add(path);
		}
	}
}
