/** * Copyright (c) 2010-2012 Kenn Hussey and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Common Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/cpl-v10.html * * Contributors: * Kenn Hussey - Initial API and implementation */ package org.eclipse.emf.oda.ecore.ui.impl; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.regex.Pattern; import org.eclipse.datatools.connectivity.oda.IConnection; import org.eclipse.datatools.connectivity.oda.IDriver; import org.eclipse.datatools.connectivity.oda.IParameterMetaData; import org.eclipse.datatools.connectivity.oda.IQuery; import org.eclipse.datatools.connectivity.oda.IResultSetMetaData; import org.eclipse.datatools.connectivity.oda.OdaException; import org.eclipse.datatools.connectivity.oda.design.DataElementAttributes; import org.eclipse.datatools.connectivity.oda.design.DataSetDesign; import org.eclipse.datatools.connectivity.oda.design.DataSetParameters; import org.eclipse.datatools.connectivity.oda.design.DesignFactory; import org.eclipse.datatools.connectivity.oda.design.ParameterDefinition; import org.eclipse.datatools.connectivity.oda.design.ParameterMode; import org.eclipse.datatools.connectivity.oda.design.ResultSetColumns; import org.eclipse.datatools.connectivity.oda.design.ResultSetDefinition; import org.eclipse.datatools.connectivity.oda.design.ui.designsession.DesignSessionUtil; import org.eclipse.datatools.connectivity.oda.design.ui.wizards.DataSetWizardPage; import org.eclipse.datatools.connectivity.oda.design.util.DesignUtil; import org.eclipse.datatools.connectivity.oda.spec.QuerySpecification; import org.eclipse.datatools.connectivity.oda.spec.util.QuerySpecificationHelper; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.TreeIterator; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.common.util.UniqueEList; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EClassifier; import org.eclipse.emf.ecore.EDataType; import org.eclipse.emf.ecore.EEnum; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EcorePackage; import org.eclipse.emf.ecore.provider.EcoreEditPlugin; import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.ecore.util.QueryDelegate; import org.eclipse.emf.edit.ui.provider.ExtendedImageRegistry; import org.eclipse.emf.edit.ui.util.QueryDelegateTextViewer; import org.eclipse.emf.oda.ecore.impl.Connection; import org.eclipse.emf.oda.ecore.impl.Driver; import org.eclipse.emf.oda.ecore.impl.ParameterMetaData; import org.eclipse.emf.oda.ecore.impl.Query; import org.eclipse.emf.oda.ecore.ui.ODAEcoreUIPlugin; import org.eclipse.emf.oda.ecore.util.StringUtil; import org.eclipse.jface.layout.GridDataFactory; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.text.Document; import org.eclipse.jface.text.ITextListener; import org.eclipse.jface.text.ITextViewer; import org.eclipse.jface.text.TextEvent; import org.eclipse.jface.text.TextViewer; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ISelection; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TableLayout; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.window.Window; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.StackLayout; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.MouseAdapter; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.dialogs.ElementListSelectionDialog; /** * Implementation of an EMF ODA data set designer page for a user to create or edit a data set * design instance. */ public class EcoreDataSetWizardPage extends DataSetWizardPage { protected static String DEFAULT_MESSAGE = ODAEcoreUIPlugin.INSTANCE.getString("_UI_DefaultDataSet_message"); //$NON-NLS-1$ protected Combo queryDelegateCombo = null; protected Map<String, ITextViewer> queryTextViewers = new HashMap<String, ITextViewer>(); protected Composite queryTextViewerComposite = null; protected StackLayout queryTextViewerStackLayout = null; protected TableViewer variablesViewer = null; protected List<Variable> variables = new UniqueEList<Variable>(); protected Text contextTypeField = null; protected EClassifier contextType = null; protected Text resultTypeField = null; protected EClassifier resultType = null; public EcoreDataSetWizardPage(String pageName) { super(pageName); setTitle(pageName); setMessage(DEFAULT_MESSAGE); setImageDescriptor(ExtendedImageRegistry.INSTANCE.getImageDescriptor(ODAEcoreUIPlugin.INSTANCE.getImage("full/wizban/NewEcore"))); //$NON-NLS-1$ } public EcoreDataSetWizardPage(String pageName, String title, ImageDescriptor titleImage) { super(pageName, title, titleImage); setMessage(DEFAULT_MESSAGE); } @Override public void createPageCustomControl(Composite parent) { setControl(createPageControl(parent)); initializeControl(); } /** * Creates custom page control for user-defined queries. */ protected Control createPageControl(Composite parent) { Composite composite = new Composite(parent, SWT.NONE); composite.setLayout(new GridLayout(3, false)); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).applyTo(composite); createQueryDelegateControl(composite); createContextTypeControl(composite); createVariablesControl(composite); createQueryTextControl(composite); createResultTypeControl(composite); setPageComplete(false); return composite; } /** * Creates control for query delegate property. */ protected void createQueryDelegateControl(Composite parent) { Label queryDelegateLabel = new Label(parent, SWT.NONE); queryDelegateLabel.setText(ODAEcoreUIPlugin.INSTANCE.getString("_UI_QueryDelegate_label")); //$NON-NLS-1$ queryDelegateCombo = new Combo(parent, SWT.BORDER | SWT.READ_ONLY); queryDelegateCombo.addModifyListener(new ModifyListener() { public void modifyText(ModifyEvent me) { String queryDelegate = getQueryDelegate(); QueryDelegateTextViewer.Factory factory = (QueryDelegateTextViewer.Factory)QueryDelegateTextViewer.Factory.Registry.INSTANCE.get(queryDelegate); ITextViewer queryTextViewer = queryTextViewers.get(queryDelegate); if (queryTextViewer == null) { queryTextViewer = factory != null ? factory.createTextViewer(queryTextViewerComposite, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL) : new TextViewer( queryTextViewerComposite, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL); if (queryTextViewer.getDocument() == null) { queryTextViewer.setDocument(new Document()); } queryTextViewer.addTextListener(new ITextListener() { public void textChanged(TextEvent te) { validateData(); } }); queryTextViewers.put(queryDelegate, queryTextViewer); } queryTextViewerStackLayout.topControl = queryTextViewer.getTextWidget(); queryTextViewerComposite.layout(); validateData(); } }); for (String uri : QueryDelegate.Factory.Registry.INSTANCE.keySet()) { queryDelegateCombo.add(uri); } GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).span(2, 1).applyTo(queryDelegateCombo); } /** * A provider of formatted labels for types. */ protected class TypeLabelProvider extends LabelProvider { @Override public String getText(Object element) { return StringUtil.getTypeText((EClassifier)element); } @Override public Image getImage(Object element) { String typeName = element instanceof EClass ? "EClass" : (element instanceof EEnum ? "EEnum" : "EDataType"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ return ExtendedImageRegistry.getInstance().getImage(EcoreEditPlugin.INSTANCE.getImage("full/obj16/" + typeName)); //$NON-NLS-1$ } } /** * Opens a dialog prompting the user to select a context type. */ protected void promptForContextTypeSelection() { ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), new TypeLabelProvider()); dialog.setMessage(ODAEcoreUIPlugin.INSTANCE.getString("_UI_SelectContextType")); //$NON-NLS-1$ dialog.setFilter("*"); //$NON-NLS-1$ dialog.setTitle(ODAEcoreUIPlugin.INSTANCE.getString("_UI_ContextTypeSelection_title")); //$NON-NLS-1$ dialog.setElements(getClassChoices()); if (contextType != null) { dialog.setInitialElementSelections(Collections.singletonList(contextType)); } if (dialog.open() == Window.OK) { setContextType((EClass)dialog.getFirstResult()); validateData(); } } /** * Creates control for context type property. */ protected void createContextTypeControl(Composite parent) { Label contextTypeLabel = new Label(parent, SWT.NONE); contextTypeLabel.setText(ODAEcoreUIPlugin.INSTANCE.getString("_UI_ContextType_label")); //$NON-NLS-1$ contextTypeField = new Text(parent, SWT.BORDER | SWT.READ_ONLY); contextTypeField.addMouseListener(new MouseAdapter() { @Override public void mouseDoubleClick(MouseEvent me) { promptForContextTypeSelection(); } }); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(contextTypeField); Button contextTypeButton = new Button(parent, SWT.PUSH); contextTypeButton.setText(ODAEcoreUIPlugin.INSTANCE.getString("_UI_Select_label")); //$NON-NLS-1$ contextTypeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent se) { promptForContextTypeSelection(); } }); } /** * Representation of an expression variable. */ protected static class Variable { protected final String name; protected final EClassifier type; protected Variable(String name, EClassifier type) { super(); this.name = name; this.type = type; } /** * Returns the name of this expression variable. * @return the name */ protected String getName() { return name; } /** * Returns the type of this expression variable. * @return the type */ protected EClassifier getType() { return type; } } /** * A dialog which prompts the user to specify a name and select a type for an * expression variable. */ protected class VariableSpecificationDialog extends ElementListSelectionDialog { protected Text nameField = null; protected String initialName = null; protected VariableSpecificationDialog(Shell shell) { super(shell, new TypeLabelProvider()); setMessage(ODAEcoreUIPlugin.INSTANCE.getString("_UI_SpecifyNameSelectType")); //$NON-NLS-1$ setFilter("*"); //$NON-NLS-1$ setElements(getClassifierChoices()); } @Override protected void computeResult() { Object[] selectedElements = getSelectedElements(); setResult(Collections.singletonList(new Variable(nameField.getText(), (EClassifier)selectedElements[0]))); } @Override protected Text createFilterText(Composite parent) { nameField = new Text(parent, SWT.BORDER); nameField.setText(initialName == null ? ODAEcoreUIPlugin.INSTANCE.getString("_UI_VariableName_label") : initialName); //$NON-NLS-1$ GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(nameField); return super.createFilterText(parent); } protected void setInitialName(String initialName) { this.initialName = initialName; } } /** * Creates control for expression variables property. */ protected void createVariablesControl(Composite parent) { Label variablesLabel = new Label(parent, SWT.NONE); variablesLabel.setText(ODAEcoreUIPlugin.INSTANCE.getString("_UI_Variables_label")); //$NON-NLS-1$ final Table variablesTable = new Table(parent, SWT.BORDER | SWT.FULL_SELECTION | SWT.MULTI); TableLayout tableLayout = new TableLayout(); tableLayout.addColumnData(new ColumnWeightData(2)); tableLayout.addColumnData(new ColumnWeightData(3)); variablesTable.setLayout(tableLayout); GridDataFactory.fillDefaults().grab(true, true).applyTo(variablesTable); variablesTable.setHeaderVisible(true); variablesTable.setLinesVisible(true); TableColumn nameColumn = new TableColumn(variablesTable, SWT.NONE); nameColumn.setText(ODAEcoreUIPlugin.INSTANCE.getString("_UI_VariableName_label")); //$NON-NLS-1$ TableColumn typeColumn = new TableColumn(variablesTable, SWT.NONE); typeColumn.setText(ODAEcoreUIPlugin.INSTANCE.getString("_UI_VariableType_label")); //$NON-NLS-1$ variablesViewer = new TableViewer(variablesTable); variablesViewer.setContentProvider(new IStructuredContentProvider() { public void inputChanged(Viewer viewer, Object oldInput, Object newInput) { ITextViewer queryTextViewer = getQueryTextViewer(); if (queryTextViewer instanceof QueryDelegateTextViewer) { ((QueryDelegateTextViewer)queryTextViewer).setParameters(convertVariablesToMap(getVariables())); } } public void dispose() { // Ignore } @SuppressWarnings("unchecked") public Object[] getElements(Object inputElement) { return ((List<Variable>)inputElement).toArray(); } }); variablesViewer.setLabelProvider(new ITableLabelProvider() { public void removeListener(ILabelProviderListener listener) { // Ignore } public boolean isLabelProperty(Object element, String property) { return false; } public void dispose() { // Ignore } public void addListener(ILabelProviderListener listener) { // Ignore } public String getColumnText(Object element, int columnIndex) { Variable variable = (Variable)element; return columnIndex == 0 ? variable.getName() : StringUtil.getTypeText(variable.getType()); } public Image getColumnImage(Object element, int columnIndex) { return null; } }); Composite variablesButtons = new Composite(parent, SWT.NONE); GridLayout gridLayout = new GridLayout(1, true); gridLayout.marginWidth = 0; variablesButtons.setLayout(gridLayout); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).applyTo(variablesButtons); Button newButton = new Button(variablesButtons, SWT.PUSH); newButton.setText(ODAEcoreUIPlugin.INSTANCE.getString("_UI_VariableNew_label")); //$NON-NLS-1$ newButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent se) { VariableSpecificationDialog dialog = new VariableSpecificationDialog(getShell()); dialog.setTitle(ODAEcoreUIPlugin.INSTANCE.getString("_UI_VariableNew_title")); //$NON-NLS-1$ if (dialog.open() == Window.OK) { List<Variable> variables = getVariables(); variables.add((Variable)dialog.getFirstResult()); variablesViewer.setInput(variables); validateData(); } } }); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).applyTo(newButton); final Button editButton = new Button(variablesButtons, SWT.PUSH); editButton.setText(ODAEcoreUIPlugin.INSTANCE.getString("_UI_VariableEdit_label")); //$NON-NLS-1$ editButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent se) { VariableSpecificationDialog dialog = new VariableSpecificationDialog(getShell()); dialog.setTitle(ODAEcoreUIPlugin.INSTANCE.getString("_UI_VariableEdit_title")); //$NON-NLS-1$ Variable variable = (Variable)((IStructuredSelection)variablesViewer.getSelection()).getFirstElement(); dialog.setInitialName(variable.getName()); dialog.setInitialElementSelections(Collections.singletonList(variable.getType())); if (dialog.open() == Window.OK) { List<Variable> variables = getVariables(); variables.set(variables.indexOf(variable), (Variable)dialog.getFirstResult()); variablesViewer.setInput(variables); validateData(); } } }); editButton.setEnabled(false); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).applyTo(editButton); final Button removeButton = new Button(variablesButtons, SWT.PUSH); removeButton.setText(ODAEcoreUIPlugin.INSTANCE.getString("_UI_VariableRemove_label")); //$NON-NLS-1$ removeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent se) { List<Variable> variables = getVariables(); ISelection selection = variablesViewer.getSelection(); for (Iterator< ? > selections = ((IStructuredSelection)selection).iterator(); selections.hasNext();) { variables.remove(selections.next()); } variablesViewer.setInput(variables); validateData(); } }); removeButton.setEnabled(false); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).applyTo(removeButton); variablesViewer.addSelectionChangedListener(new ISelectionChangedListener() { public void selectionChanged(SelectionChangedEvent sce) { IStructuredSelection selection = (IStructuredSelection)sce.getSelection(); editButton.setEnabled(selection.size() == 1); removeButton.setEnabled(selection.size() > 0); } }); } /** * Creates control for query text. */ protected void createQueryTextControl(Composite parent) { Label queryTextLabel = new Label(parent, SWT.NONE); queryTextLabel.setText(ODAEcoreUIPlugin.INSTANCE.getString("_UI_QueryText_label")); //$NON-NLS-1$ (queryTextViewerComposite = new Composite(parent, SWT.NONE)).setLayout(queryTextViewerStackLayout = new StackLayout()); GridDataFactory.fillDefaults().grab(true, true).span(2, 1).applyTo(queryTextViewerComposite); } /** * Opens a dialog prompting the user to select a result type. */ protected void promptForResultTypeSelection() { ElementListSelectionDialog dialog = new ElementListSelectionDialog(getShell(), new TypeLabelProvider()); dialog.setMessage(ODAEcoreUIPlugin.INSTANCE.getString("_UI_SelectResultType")); //$NON-NLS-1$ dialog.setFilter("*"); //$NON-NLS-1$ dialog.setTitle(ODAEcoreUIPlugin.INSTANCE.getString("_UI_ResultTypeSelection_title")); //$NON-NLS-1$ dialog.setElements(getClassifierChoices()); if (resultType != null) { dialog.setInitialElementSelections(Collections.singletonList(resultType)); } if (dialog.open() == Window.OK) { setResultType((EClassifier)dialog.getFirstResult()); validateData(); } } /** * Creates control for result type property. */ protected void createResultTypeControl(Composite parent) { Label resultTypeLabel = new Label(parent, SWT.NONE); resultTypeLabel.setText(ODAEcoreUIPlugin.INSTANCE.getString("_UI_ResultType_label")); //$NON-NLS-1$ resultTypeField = new Text(parent, SWT.BORDER | SWT.READ_ONLY); resultTypeField.addMouseListener(new MouseAdapter() { @Override public void mouseDoubleClick(MouseEvent me) { promptForResultTypeSelection(); } }); GridDataFactory.fillDefaults().align(SWT.FILL, SWT.CENTER).grab(true, false).applyTo(resultTypeField); Button resultTypeButton = new Button(parent, SWT.PUSH); resultTypeButton.setText(ODAEcoreUIPlugin.INSTANCE.getString("_UI_Select_label")); //$NON-NLS-1$ resultTypeButton.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent se) { promptForResultTypeSelection(); } }); } /** * Initializes the page control with the last edited data set design. */ protected void initializeControl() { // restore the last saved data set design DataSetDesign dataSetDesign = getEditingDesign(); if (dataSetDesign == null) { return; // nothing to initialize } Properties properties = DesignUtil.convertDesignProperties(dataSetDesign.getPublicProperties()); String queryDelegate = properties.getProperty(Query.DELEGATE_PROPERTY_NAME); if (!StringUtil.isEmpty(queryDelegate)) { // initialize query delegate queryDelegateCombo.setText(queryDelegate); } else if (queryDelegateCombo.getItemCount() > 0) { queryDelegateCombo.setText(queryDelegateCombo.getItem(0)); } String queryText = dataSetDesign.getQueryText(); if (!StringUtil.isEmpty(queryText)) { // initialize query text getQueryTextViewer().getDocument().set(queryText); } String context = properties.getProperty(Query.CONTEXT_PROPERTY_NAME); if (!StringUtil.isEmpty(context)) { // initialize context type try { setContextType(getTypeFromString(context)); } catch (Exception e) { // ignore } } String string = properties.getProperty(Query.VARIABLES_PROPERTY_NAME); if (!StringUtil.isEmpty(string)) { // initialize expression variables try { List<Variable> variables = getVariables(); variables.addAll(getVariablesFromString(string)); variablesViewer.setInput(variables); } catch (Exception e) { // ignore } } String type = properties.getProperty(Query.TYPE_PROPERTY_NAME); if (!StringUtil.isEmpty(type)) { // initialize result type try { setResultType(getTypeFromString(type)); } catch (Exception e) { // ignore } } validateData(); setMessage(DEFAULT_MESSAGE); } protected Object[] classChoices = null; /** * Returns an array of classes applicable for the data source. * @return the applicable classes */ protected Object[] getClassChoices() { if (classChoices == null) { EList<Object> choices = new UniqueEList.FastCompare<Object>(); choices.addAll(EcoreUtil.getObjectsByType(Arrays.asList(getClassifierChoices()), EcorePackage.Literals.ECLASS)); classChoices = choices.toArray(); } return classChoices; } protected Object[] classifierChoices = null; /** * Returns an array of classes and data types applicable for the data source. * @return the applicable classes and data types */ protected Object[] getClassifierChoices() { if (classifierChoices == null) { EList<Object> choices = new UniqueEList.FastCompare<Object>(); Connection connection = null; try { IDriver driver = new Driver(); connection = (Connection)driver.getConnection(null); java.util.Properties properties = DesignSessionUtil.getEffectiveDataSourceProperties(getEditingDesign().getDataSourceDesign()); connection.open(properties); for (TreeIterator<Object> allContents = EcoreUtil.getAllContents(connection.getResourceSet(), true); allContents.hasNext();) { Object next = allContents.next(); if (next instanceof EObject) { EClass eClass = ((EObject)next).eClass(); if (!choices.contains(eClass)) { choices.add(eClass); choices.addAll(eClass.getEAllSuperTypes()); for (EAttribute eAttribute : eClass.getEAllAttributes()) { EDataType eType = eAttribute.getEAttributeType(); if (eType != null) { choices.add(eType); } } } } } } catch (OdaException oe) { oe.printStackTrace(); } finally { closeConnection(connection); } classifierChoices = choices.toArray(); } return classifierChoices; } /** * Converts the specified type to its string representation. * @param type the type * @return the string representation */ protected String convertTypeToString(EClassifier type) { return EcoreUtil.getURI(type).toString(); } /** * Retrieves the type corresponding to the specified string representation. * @param string the string representation * @return the type */ protected EClassifier getTypeFromString(String string) { return (EClassifier)new ResourceSetImpl().getEObject(URI.createURI(string), true); } /** * Converts the specified expression variables to a string representation. * @param variables the expression variables * @return the string representation */ protected String convertVariablesToString(List<Variable> variables) { StringBuilder sb = new StringBuilder(); for (Variable variable : variables) { sb.append(variable.getName()); sb.append(' '); sb.append(convertTypeToString(variable.getType())); sb.append(' '); } return sb.toString().trim(); } /** * Converts the specified expression variables to a map representation. * @param variables the expression variables * @return the map representation */ protected Map<String, EClassifier> convertVariablesToMap(List<Variable> variables) { Map<String, EClassifier> map = new HashMap<String, EClassifier>(); for (Variable variable : variables) { map.put(variable.getName(), variable.getType()); } return map; } /** * Retrieves the expression variables corresponding to the specified string representation. * @param string the string representation * @return the variables */ protected List<Variable> getVariablesFromString(String string) { List<Variable> variables = new UniqueEList<Variable>(); String[] strings = string.split(Pattern.quote(" ")); //$NON-NLS-1$ for (int i = 0; i < strings.length; i += 2) { variables.add(new Variable(strings[i], getTypeFromString(strings[i + 1]))); } return variables; } /** * Returns the value of the query delegate property. * @return the query delegate */ protected String getQueryDelegate() { return queryDelegateCombo == null || queryDelegateCombo.isDisposed() ? null : queryDelegateCombo.getText(); } /** * Returns the value of the expression variables property. * @return the expression variables */ protected List<Variable> getVariables() { return variables; } protected ITextViewer getQueryTextViewer() { return queryTextViewers.get(getQueryDelegate()); } /** * Returns the value of the query text. * @return the query text */ protected String getQueryText() { ITextViewer queryTextViewer = getQueryTextViewer(); return queryTextViewer == null ? null : queryTextViewer.getDocument().get(); } /** * Returns the value of the context type property. * @return the context type */ protected EClassifier getContextType() { return contextType; } /** * Sets the value of the context type property. * @param contextType the value */ protected void setContextType(EClassifier contextType) { this.contextType = contextType; if (contextTypeField != null) { contextTypeField.setText(StringUtil.getTypeText(contextType)); } ITextViewer queryTextViewer = getQueryTextViewer(); if (queryTextViewer instanceof QueryDelegateTextViewer) { ((QueryDelegateTextViewer)queryTextViewer).setContext(contextType); } } /** * Returns the value of the result type property. * @return the result type */ protected EClassifier getResultType() { return resultType; } /** * Sets the value of the result type property. * @param resultType the value */ protected void setResultType(EClassifier resultType) { this.resultType = resultType; if (resultTypeField != null) { resultTypeField.setText(StringUtil.getTypeText(resultType)); } } @Override protected DataSetDesign collectDataSetDesign(DataSetDesign design) { if (getControl() == null) // page control was never created { return design; // no editing was done } if (!hasValidData()) { return null; // trigger a design session error status } savePage(design); return design; } @Override protected boolean canLeave() { return isPageComplete(); } /** * Validates that the user has specified values for the properties in the page control * and sets page message accordingly. */ protected void validateData() { QueryDelegate.Factory factory = (QueryDelegate.Factory)QueryDelegate.Factory.Registry.INSTANCE.get(getQueryDelegate()); boolean isValid = factory != null; if (factory != null) { EClassifier context = getContextType(); isValid = context != null; if (isValid) { String queryText = getQueryText(); isValid = !StringUtil.isEmpty(queryText); if (isValid) { isValid = getResultType() != null; if (isValid) { try { List<Variable> variables = getVariables(); Map<String, EClassifier> map = variables.isEmpty() ? null : convertVariablesToMap(variables); factory.createQueryDelegate(context, map, queryText).prepare(); setMessage(DEFAULT_MESSAGE); } catch (Exception e) { isValid = false; Throwable cause = e.getCause(); setMessage(cause == null ? e.getLocalizedMessage() : cause.getLocalizedMessage(), ERROR); } } else { setMessage(ODAEcoreUIPlugin.INSTANCE.getString("_UI_ResultTypeCannotBeEmpty_message"), ERROR); //$NON-NLS-1$ } } else { setMessage(ODAEcoreUIPlugin.INSTANCE.getString("_UI_QueryTextCannotBeEmpty_message"), ERROR); //$NON-NLS-1$ } } else { setMessage(ODAEcoreUIPlugin.INSTANCE.getString("_UI_ContextTypeCannotBeEmpty_message"), ERROR); //$NON-NLS-1$ } } else { setMessage(ODAEcoreUIPlugin.INSTANCE.getString("_UI_QueryDelegateCannotBeEmpty_message"), ERROR); //$NON-NLS-1$ } setPageComplete(isValid); } /** * Indicates whether the custom page has valid data to proceed * with defining a data set. */ protected boolean hasValidData() { validateData(); return canLeave(); } /** * Saves the user-defined values in this page, and updates the specified * data set design with the latest design definition. */ protected void savePage(DataSetDesign dataSetDesign) { // save user-defined query text String queryText = getQueryText(); dataSetDesign.setQueryText(queryText); // obtain query's current runtime metadata, and maps it to the dataSetDesign IConnection connection = null; try { // instantiate runtime driver class IDriver driver = new Driver(); // obtain and open a live connection connection = driver.getConnection(null); java.util.Properties properties = DesignSessionUtil.getEffectiveDataSourceProperties(getEditingDesign().getDataSourceDesign()); connection.open(properties); // update the data set design with the // query's current runtime metadata updateDesign(dataSetDesign, connection, queryText); } catch (OdaException oe) { // not able to get current metadata, reset previous derived metadata dataSetDesign.setResultSets(null); dataSetDesign.setParameters(null); oe.printStackTrace(); } finally { closeConnection(connection); } } /** * Updates the given data set design with the proeprties and derived metadata * obtained from the ODA runtime connection. */ protected void updateDesign(DataSetDesign dataSetDesign, IConnection connection, String queryText) throws OdaException { IQuery query = connection.newQuery(null); QuerySpecificationHelper helper = new QuerySpecificationHelper((String)null); QuerySpecification specification = helper.createQuerySpecification(); specification.setProperty(Query.DELEGATE_PROPERTY_NAME, getQueryDelegate()); specification.setProperty(Query.CONTEXT_PROPERTY_NAME, convertTypeToString(getContextType())); specification.setProperty(Query.TYPE_PROPERTY_NAME, convertTypeToString(getResultType())); specification.setParameterValue(specification.new ParameterIdentifier(ParameterMetaData.TARGET_PARAMETER_NAME, 1), null); List<Variable> variables = getVariables(); specification.setProperty(Query.VARIABLES_PROPERTY_NAME, convertVariablesToString(variables)); for (int i = 0; i < variables.size(); i++) { specification.setParameterValue(specification.new ParameterIdentifier(variables.get(i).getName(), i + 2), null); } query.setSpecification(specification); Properties properties = new Properties(); properties.putAll(specification.getProperties()); dataSetDesign.setPublicProperties(DesignUtil.convertToDesignProperties(properties)); query.prepare(queryText); try { updateResultSetDesign(query.getMetaData(), dataSetDesign); } catch (OdaException oe) { // no result set definition available, reset previous derived metadata dataSetDesign.setResultSets(null); oe.printStackTrace(); } // proceed to get parameter design definition try { updateParameterDesign(query.getParameterMetaData(), dataSetDesign); } catch (OdaException oe) { // no parameter definition available, reset previous derived metadata dataSetDesign.setParameters(null); oe.printStackTrace(); } } /** * Updates the specified data set design's result set definition based on the * specified runtime metadata. * @param resultSetMetaData runtime result set metadata instance * @param dataSetDesign data set design instance to update * @throws OdaException */ protected void updateResultSetDesign(IResultSetMetaData resultSetMetaData, DataSetDesign dataSetDesign) throws OdaException { ResultSetColumns columns = DesignSessionUtil.toResultSetColumnsDesign(resultSetMetaData); ResultSetDefinition definition = DesignFactory.eINSTANCE.createResultSetDefinition(); definition.setResultSetColumns(columns); // no exception in conversion; go ahead and assign to specified data set design dataSetDesign.setPrimaryResultSet(definition); dataSetDesign.getResultSets().setDerivedMetaData(true); } /** * Updates the specified data set design's parameter definition based on the * specified runtime metadata. * @param parameterMetaData runtime parameter metadata instance * @param dataSetDesign data set design instance to update * @throws OdaException */ protected void updateParameterDesign(IParameterMetaData parameterMetaData, DataSetDesign dataSetDesign) throws OdaException { ParameterMode mode = DesignSessionUtil.toParameterModeDesign(IParameterMetaData.parameterModeIn); DataSetParameters parameters = DesignSessionUtil.toDataSetParametersDesign(parameterMetaData, mode); // no exception in conversion; go ahead and assign to specified data set design dataSetDesign.setParameters(parameters); if (parameters == null) { return; // no parameter definitions; done with update } ParameterMetaData metaData = (ParameterMetaData)parameterMetaData; for (ParameterDefinition parameterDefinition : parameters.getParameterDefinitions()) { DataElementAttributes attributes = parameterDefinition.getAttributes(); if (attributes != null && attributes.isSetNativeDataTypeCode()) { parameterDefinition.addDefaultValue(metaData.getParameterDefaultValue(attributes.getName())); } } parameters.setDerivedMetaData(true); } /** * Attempts to close the given ODA connection. */ protected void closeConnection(IConnection connection) { try { if (connection != null && connection.isOpen()) { connection.close(); } } catch (OdaException e) { // ignore e.printStackTrace(); } } }