/* * Copyright (C) 2012 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.motorola.studio.android.codeutils.codegeneration; import java.io.IOException; import java.util.HashSet; import java.util.Set; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IProject; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Status; import org.eclipse.datatools.connectivity.ConnectionProfileException; import org.eclipse.datatools.modelbase.sql.schema.Database; import org.eclipse.datatools.modelbase.sql.tables.Table; import org.eclipse.jface.dialogs.IPageChangeProvider; import org.eclipse.jface.dialogs.IPageChangedListener; import org.eclipse.jface.dialogs.PageChangedEvent; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ITreeSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TreeNode; import org.eclipse.jface.viewers.TreeNodeContentProvider; import org.eclipse.jface.viewers.TreeSelection; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Composite; import com.motorola.studio.android.codeutils.CodeUtilsActivator; import com.motorola.studio.android.codeutils.db.utils.DatabaseUtils; import com.motorola.studio.android.codeutils.i18n.CodeUtilsNLS; import com.motorola.studio.android.common.exception.AndroidException; import com.motorola.studio.android.common.log.StudioLogger; import com.motorola.studio.android.common.utilities.AndroidUtils; import com.motorola.studio.android.model.ActivityBasedOnTemplate; import com.motorola.studio.android.wizards.buildingblocks.Method; import com.motorola.studio.android.wizards.buildingblocks.NewLauncherWizardPage; /** * Wizard page to create an activity based on database samples. * */ public class CreateSampleDatabaseActivityPage extends NewLauncherWizardPage { private TreeViewer treeViewer; //Tree viewer input private TreeNode[] treeNodeArray; // Page help ID public static final String PAGE_HELP_ID = CodeUtilsActivator.PLUGIN_ID + ".selecttablepage"; // ANDROID_METADATA Table name private static final String ANDROID_METADATA_TABLE_NAME = "ANDROID_METADATA"; // Can flip to next page flag private boolean canFlip = false; /** * Default constructor. * </br></br> * Creates a new instance using {@link com.motorola.studio.android.wizards.buildingblocks.NewLauncherWizardPage#NewLauncherWizardPage(com.motorola.studio.android.model.BuildingBlockModel,java.lang.String) NewLauncherWizardPage(BuildingBlockModel, String)} * and passing {@code null} and {@link CodeUtilsNLS#UI_CreateSampleDatabaseActivityPageName Page name} as arguments. */ public CreateSampleDatabaseActivityPage() { super(null, CodeUtilsNLS.UI_CreateSampleDatabaseActivityPageName); } /** * Creates a new instance using {@link com.motorola.studio.android.wizards.buildingblocks.NewLauncherWizardPage#NewLauncherWizardPage(com.motorola.studio.android.model.BuildingBlockModel,java.lang.String) NewLauncherWizardPage(BuildingBlockModel, String)} * and passing {@code activity} and {@link CodeUtilsNLS#UI_CreateSampleDatabaseActivityPageName Page name} as arguments. * * @param activity an {@code com.motorola.studio.android.model.ActivityBasedOnTemplate} to be used as the building block model. */ public CreateSampleDatabaseActivityPage(ActivityBasedOnTemplate activity) { super(activity, CodeUtilsNLS.UI_CreateSampleDatabaseActivityPageName); } /* (non-Javadoc) * @see com.motorola.studio.android.wizards.buildingblocks.NewBuildingBlocksWizardPage#createIntermediateControls(org.eclipse.swt.widgets.Composite) */ @Override protected void createExtendedControls(Composite parent) { Composite mainComposite = new Composite(parent, SWT.NONE); mainComposite.setLayout(new GridLayout()); mainComposite.setLayoutData(new GridData(GridData.FILL_BOTH)); mainComposite.setLayout(new GridLayout()); Composite composite = new Composite(mainComposite, SWT.NONE); composite.setLayout(new GridLayout()); composite.setLayoutData(new GridData(GridData.FILL_BOTH)); // Databases and Tables Tree Viewer treeViewer = new TreeViewer(composite, SWT.BORDER | SWT.SINGLE | SWT.V_SCROLL); treeViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); // Set content and label provider treeViewer.setLabelProvider(new SampleDatabaseActivityPageLabelProvider()); treeViewer.setContentProvider(new TreeNodeContentProvider()); // Create an array of type TreeNode[] to serve as the input for the tree if ((treeNodeArray == null) || (treeNodeArray.length < 1)) { treeNodeArray = generateTreeViewerInput(); } treeViewer.setInput(treeNodeArray); treeViewer.addSelectionChangedListener(new DatabaseTreeListener()); // Check if there were any databases found and update status if not. if (treeNodeArray.length < 1) { // Create a warning status IStatus status = new Status( IStatus.WARNING, CodeUtilsActivator.PLUGIN_ID, CodeUtilsNLS.UI_CreateSampleDatabaseActivityPage_No_Database_Found_Information); updateStatus(status); } // Expand all elements treeViewer.expandAll(); // Add a listener to the wizard to listen for page changes if (getContainer() instanceof IPageChangeProvider) { ((IPageChangeProvider) getContainer()).addPageChangedListener(new PageChangeListener()); } setControl(mainComposite); } /* (non-Javadoc) * @see com.motorola.studio.android.wizards.buildingblocks.NewLauncherWizardPage#getIntentFiltersActions() */ @Override protected String[] getIntentFiltersActions() { String[] intentFiltersActions = new String[0]; try { intentFiltersActions = AndroidUtils.getActivityActions(getBuildBlock().getProject()); } catch (AndroidException e) { setErrorMessage(e.getMessage()); } return intentFiltersActions; } /* (non-Javadoc) * @see com.motorola.studio.android.wizards.buildingblocks.NewBuildingBlocksWizardPage#getDefaultMessage() */ @Override public String getDefaultMessage() { return CodeUtilsNLS.UI_CreateSampleDatabaseActivityPage_Default_Message; } /* (non-Javadoc) * @see com.motorola.studio.android.wizards.buildingblocks.NewBuildingBlocksWizardPage#getHelpId() */ @Override protected String getHelpId() { return PAGE_HELP_ID; } /* (non-Javadoc) * @see com.motorola.studio.android.wizards.buildingblocks.NewBuildingBlocksWizardPage#getWizardTitle() */ @Override public String getWizardTitle() { return CodeUtilsNLS.UI_ActivityWizard_Title; } /* (non-Javadoc) * @see com.motorola.studio.android.wizards.buildingblocks.NewBuildingBlocksWizardPage#getMethods() */ @Override protected Method[] getMethods() { return null; } /* * (non-Javadoc) * */ @Override public boolean canFlipToNextPage() { return canFlip; } /* * Method to retrieve the databases and tables from the target project and make a TreeNodeArray */ private TreeNode[] generateTreeViewerInput() { // Collection of TreeNodes HashSet<TreeNode> treeNodeColletion = new HashSet<TreeNode>(); // The selected project for which the activity will be created IProject project = getBuildBlock().getProject(); if (project != null) { // Get a collection of existing .db files inside the project Set<IFile> dbFilesSet = DatabaseUtils.getDbFilesFromProject(project); // Retrieve the database instances for (IFile dbFile : dbFilesSet) { try { // For each database retrieved, construct a TreeNode object containing itself and it's tables Database database = DatabaseUtils.getDatabase(project.getName(), dbFile.getName()); TreeNode treeNodeDatabase = new TreeNode(database); // Collection to store the table treeNodes from this database. Will be used later to set the children nodes of the database. HashSet<TreeNode> databaseChildren = new HashSet<TreeNode>(); // Construct another TreeTable object for each table and set the database tree node as the parent. // Tables don't have children for (Table table : DatabaseUtils.getTables(database)) { // Do not add ANDROID_METADATA table if (!table.getName().equalsIgnoreCase(ANDROID_METADATA_TABLE_NAME)) { TreeNode treeNodeTable = new TreeNode(table); treeNodeTable.setParent(treeNodeDatabase); // Add this node as a children of the database tree node. databaseChildren.add(treeNodeTable); } } // Add the table nodes as the children of the database node treeNodeDatabase.setChildren(databaseChildren.toArray(new TreeNode[0])); // Add the database tree node to the resulting TreeNode collection that will serve as input treeNodeColletion.add(treeNodeDatabase); } catch (ConnectionProfileException e) { // Log error StudioLogger.error(DatabaseUtils.class, "A error ocurred while retrieving the connection profile.", e); } catch (IOException e) { // Log error StudioLogger.error(DatabaseUtils.class, "An I/O error ocurred.", e); } } } // Return a TreeNode array return treeNodeColletion.toArray(new TreeNode[0]); } /** * @return Returns true if page has header. Otherwise, returns false. */ @Override public boolean hasHeader() { return false; } /** * Selection listener for the tree viewer. */ class DatabaseTreeListener implements ISelectionChangedListener { /* (non-Javadoc) * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) */ public void selectionChanged(SelectionChangedEvent event) { ActivityBasedOnTemplate activity = ((ActivityBasedOnTemplate) getBuildBlock()); if (event.getSelection() instanceof ITreeSelection) { ITreeSelection treeSelection = (ITreeSelection) event.getSelection(); if (treeSelection.getFirstElement() instanceof TreeNode) { TreeNode selectedNode = (TreeNode) treeSelection.getFirstElement(); // Check if it's a database or table that was selected and set verification flags if (selectedNode.getValue() instanceof Table) { canFlip = true; // Set the collector table activity.setCollectorTable((Table) selectedNode.getValue()); // Set the collector database TreeNode parentNode = selectedNode.getParent(); activity.setCollectorDatabaseName(((Database) parentNode.getValue()) .getName()); activity.setDatabaseTableSelected(true); } else { canFlip = false; // Set the collector info to null activity.setCollectorTable(null); activity.setCollectorDatabaseName(null); activity.setDatabaseTableSelected(false); } getWizard().getContainer().updateButtons(); } } } } /** * Listener to verify when this page is visible */ private class PageChangeListener implements IPageChangedListener { /* * (non-Javadoc) * * @see * org.eclipse.jface.dialogs.IPageChangedListener#pageChanged(org.eclipse * .jface.dialogs.PageChangedEvent) */ public void pageChanged(PageChangedEvent event) { if ((event.getSelectedPage() == CreateSampleDatabaseActivityPage.this)) { ActivityBasedOnTemplate activity = (ActivityBasedOnTemplate) getBuildBlock(); treeNodeArray = generateTreeViewerInput(); treeViewer.setInput(treeNodeArray); // Check if there were any databases found and update status if not. if (treeNodeArray.length < 1) { // Create a warning status IStatus status = new Status( IStatus.WARNING, CodeUtilsActivator.PLUGIN_ID, CodeUtilsNLS.UI_CreateSampleDatabaseActivityPage_No_Database_Found_Information); updateStatus(status); } else { updateStatus(new Status(IStatus.OK, CodeUtilsActivator.PLUGIN_ID, null)); } if ((activity.getCollectorTable() == null) && (!treeViewer.getSelection().isEmpty())) { treeViewer.setSelection(TreeSelection.EMPTY); } if (treeViewer.getSelection().isEmpty()) { canFlip = false; } //update buttons getWizard().getContainer().updateButtons(); // Expand all elements treeViewer.expandAll(); } } } }