/* * JBoss, Home of Professional Open Source. * * See the LEGAL.txt file distributed with this work for information regarding copyright ownership and licensing. * * See the AUTHORS.txt file distributed with this work for a full listing of individual contributors. */ package org.teiid.designer.extension.ui.editors; import static org.teiid.designer.extension.ui.UiConstants.EditorIds.MED_PROPERTIES_PAGE; import static org.teiid.designer.extension.ui.UiConstants.Form.SECTION_STYLE; import static org.teiid.designer.extension.ui.UiConstants.Form.VIEWER_STYLE; import static org.teiid.designer.extension.ui.UiConstants.ImageIds.ADD_METACLASS; import static org.teiid.designer.extension.ui.UiConstants.ImageIds.ADD_PROPERTY; import static org.teiid.designer.extension.ui.UiConstants.ImageIds.CHECK_MARK; import static org.teiid.designer.extension.ui.UiConstants.ImageIds.EDIT_METACLASS; import static org.teiid.designer.extension.ui.UiConstants.ImageIds.EDIT_PROPERTY; import static org.teiid.designer.extension.ui.UiConstants.ImageIds.MED_EDITOR; import static org.teiid.designer.extension.ui.UiConstants.ImageIds.REMOVE_METACLASS; import static org.teiid.designer.extension.ui.UiConstants.ImageIds.REMOVE_PROPERTY; import java.beans.PropertyChangeEvent; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import org.eclipse.jface.viewers.ColumnLabelProvider; import org.eclipse.jface.viewers.DoubleClickEvent; import org.eclipse.jface.viewers.IDoubleClickListener; 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.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TableViewerColumn; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.window.Window; import org.eclipse.osgi.util.NLS; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.ui.forms.IMessageManager; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.Section; import org.teiid.core.designer.util.ArrayUtil; import org.teiid.core.designer.util.CoreStringUtil; import org.teiid.designer.core.extension.AbstractMetaclassNameProvider; import org.teiid.designer.core.extension.ModelTypeMetaclassNameFactory; import org.teiid.designer.extension.ExtensionPlugin; import org.teiid.designer.extension.definition.ExtendableMetaclassNameProvider; import org.teiid.designer.extension.definition.MedStatus; import org.teiid.designer.extension.definition.ModelExtensionDefinition.PropertyName; import org.teiid.designer.extension.definition.ModelExtensionDefinitionValidator; import org.teiid.designer.extension.definition.ValidationStatus; import org.teiid.designer.extension.properties.ModelExtensionPropertyDefinition; import org.teiid.designer.extension.ui.Activator; import org.teiid.designer.extension.ui.Messages; import org.teiid.designer.extension.ui.model.MedModelNode; import org.teiid.designer.extension.ui.model.MedModelNode.ModelType; import org.teiid.designer.ui.common.util.WidgetUtil; import org.teiid.designer.ui.forms.FormUtil; import org.teiid.designer.ui.forms.MessageFormDialog; /** * Provides Properties editing tab of the ModelExtensionDefinitionEditor */ public class PropertiesEditorPage extends MedEditorPage { private Button btnAddMetaclass; private Button btnAddProperty; private Button btnEditMetaclass; private Button btnEditProperty; private Button btnRemoveMetaclass; private Button btnRemoveProperty; private TableViewer metaclassViewer; private MedSelectionProvider metaclassSelectionProvider; private TableViewer propertyViewer; private MedSelectionProvider propertySelectionProvider; private final ErrorMessage metaclassError; private final ErrorMessage propertyError; /** * Constructor * @param medEditor the MED editor this page belongs to (cannot be <code>null</code>) */ public PropertiesEditorPage( ModelExtensionDefinitionEditor medEditor ) { super(medEditor, MED_PROPERTIES_PAGE, Messages.medEditorPropertiesPageTitle); this.metaclassError = new ErrorMessage(); this.propertyError = new ErrorMessage(); validateMetaclasses(); // this calls validatePropertyDefinitions(); } MedEditorPage accessPage() { return this; } private boolean confirmMetaclass(final String metaclassBeingValidated, final ExtendableMetaclassNameProvider provider, final String validMetaclass) { if (metaclassBeingValidated.equals(validMetaclass)) { return true; } final String[] kids = provider.getExtendableMetaclassChildren(validMetaclass); boolean confirmed = false; if ((kids != null) && (kids.length != 0)) { for (final String kid : kids) { confirmed = confirmMetaclass(metaclassBeingValidated, provider, kid); if (confirmed) { break; } } } return confirmed; } /** * {@inheritDoc} * * @see org.teiid.designer.extension.ui.editors.MedEditorPage#createBody(org.eclipse.swt.widgets.Composite, * org.eclipse.ui.forms.widgets.FormToolkit) */ @SuppressWarnings("unused") @Override protected void createBody( Composite body, FormToolkit toolkit ) { BODY: { body.setLayout(new GridLayout()); body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); } final Composite finalTop; TOP: { Composite top = toolkit.createComposite(body, SWT.NONE); top.setLayout(new GridLayout()); top.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); finalTop = top; } final Composite finalBottom; BOTTOM: { Composite bottom = toolkit.createComposite(body, SWT.NONE); bottom.setLayout(new GridLayout()); bottom.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); finalBottom = bottom; } SECTIONS: { Section metaclassSection = createExtendedMetaclassSection(finalTop, toolkit); ((GridData)finalTop.getLayoutData()).heightHint = (this.metaclassViewer.getTable().getItemHeight() * 10); Section propertiesSection = createPropertiesSection(finalBottom, toolkit); ((GridData)finalBottom.getLayoutData()).heightHint = (this.propertyViewer.getTable().getItemHeight() * 10); propertiesSection.descriptionVerticalSpacing = metaclassSection.getTextClientHeightDifference(); } // hook selection synchronizer MedSelectionSynchronizer selectionSynchronizer = getMedEditor().getSelectionSynchronizer(); this.metaclassSelectionProvider = new SelectionProvider(true); selectionSynchronizer.addSelectionProvider(this.metaclassSelectionProvider); this.propertySelectionProvider = new SelectionProvider(false); selectionSynchronizer.addSelectionProvider(this.propertySelectionProvider); // populate UI this.metaclassViewer.setInput(this); WidgetUtil.pack(this.metaclassViewer); // clear any initial messages that were created before the control was set IMessageManager msgMgr = ((ModelExtensionDefinitionEditor)getEditor()).getMessageManager(); msgMgr.removeMessage(this.metaclassError.getKey()); msgMgr.removeMessage(this.propertyError.getKey()); } private void configureColumn( TableViewerColumn viewerColumn, int columnIndex, String headerText, String headerToolTip, boolean resizable ) { viewerColumn.setLabelProvider(new PropertyLabelProvider(columnIndex)); TableColumn column = viewerColumn.getColumn(); column.setText(headerText); column.setToolTipText(headerToolTip); column.setMoveable(false); column.setResizable(resizable); column.pack(); } @SuppressWarnings("unused") private Section createExtendedMetaclassSection( Composite parent, FormToolkit toolkit ) { final Section finalSection; SECTION: { Section section = FormUtil.createSection(getManagedForm(), toolkit, parent, Messages.overviewPageExtendedMetaclassTitle, Messages.overviewPageExtendedMetaclassDescription, SECTION_STYLE, true); finalSection = section; // configure section toolbar Button[] buttons = FormUtil.createSectionToolBar(finalSection, toolkit, new Image[] { Activator.getDefault().getImage(ADD_METACLASS), Activator.getDefault().getImage(EDIT_METACLASS), Activator.getDefault().getImage(REMOVE_METACLASS) }); // configure add button this.btnAddMetaclass = buttons[0]; this.btnAddMetaclass.setEnabled(!CoreStringUtil.isEmpty(getMed().getMetamodelUri())); this.btnAddMetaclass.addSelectionListener(new SelectionAdapter() { /** * {@inheritDoc} * * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetSelected( SelectionEvent e ) { handleAddMetaclass(); } }); this.btnAddMetaclass.setToolTipText(Messages.propertiesPageAddMetaclassButtonToolTip); // configure edit button this.btnEditMetaclass = buttons[1]; this.btnEditMetaclass.setEnabled(false); this.btnEditMetaclass.addSelectionListener(new SelectionAdapter() { /** * {@inheritDoc} * * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetSelected( SelectionEvent e ) { handleEditMetaclass(); } }); this.btnEditMetaclass.setToolTipText(Messages.propertiesPageEditMetaclassButtonToolTip); // configure remove button this.btnRemoveMetaclass = buttons[2]; this.btnRemoveMetaclass.setEnabled(false); this.btnRemoveMetaclass.addSelectionListener(new SelectionAdapter() { /** * {@inheritDoc} * * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetSelected( SelectionEvent e ) { handleRemoveMetaclass(); } }); this.btnRemoveMetaclass.setToolTipText(Messages.propertiesPageRemoveMetaclassButtonToolTip); } final Composite finalContainer; CONTAINER: { Composite container = toolkit.createComposite(finalSection); finalContainer = container; container.setLayout(new GridLayout()); container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); finalSection.setClient(container); } VIEWER: { Table table = toolkit.createTable(finalContainer, VIEWER_STYLE); table.setLayoutData(new GridLayout()); table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); ((GridData)table.getLayoutData()).heightHint = table.getItemHeight() * 5; this.metaclassError.setControl(table); this.metaclassViewer = new TableViewer(table); this.metaclassViewer.setContentProvider(new IStructuredContentProvider() { /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.IContentProvider#dispose() */ @Override public void dispose() { // nothing to do } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) */ @Override public Object[] getElements( Object inputElement ) { return getMed().getExtendedMetaclasses(); } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, * java.lang.Object) */ @Override public void inputChanged( Viewer viewer, Object oldInput, Object newInput ) { // nothing to do } }); this.metaclassViewer.setLabelProvider(new LabelProvider() { @Override public String getText( Object element ) { String elemString = element.toString(); return getMetaclassShortName(elemString); } }); this.metaclassViewer.addDoubleClickListener(new IDoubleClickListener() { /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.IDoubleClickListener#doubleClick(org.eclipse.jface.viewers.DoubleClickEvent) */ @Override public void doubleClick( DoubleClickEvent event ) { handleEditMetaclass(); } }); this.metaclassViewer.addSelectionChangedListener(new ISelectionChangedListener() { /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) */ @Override public void selectionChanged( SelectionChangedEvent event ) { handleMetaclassSelected(); } }); } return finalSection; } private String getMetaclassShortName( String metaclassName ) { return AbstractMetaclassNameProvider.getLabel(metaclassName); } @SuppressWarnings("unused") private Section createPropertiesSection( Composite parent, FormToolkit toolkit ) { final Section finalSection; SECTION: { Section section = FormUtil.createSection(getManagedForm(), toolkit, parent, Messages.propertiesPageExtensionPropertiesTitle, Messages.propertiesPageExtensionPropertiesDescription, SECTION_STYLE, true); finalSection = section; // configure section toolbar Button[] buttons = FormUtil.createSectionToolBar(finalSection, toolkit, new Image[] { Activator.getDefault().getImage(ADD_PROPERTY), Activator.getDefault().getImage(EDIT_PROPERTY), Activator.getDefault().getImage(REMOVE_PROPERTY) }); // configure add button this.btnAddProperty = buttons[0]; this.btnAddProperty.addSelectionListener(new SelectionAdapter() { /** * {@inheritDoc} * * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetSelected( SelectionEvent e ) { handleAddProperty(); } }); this.btnAddProperty.setToolTipText(Messages.propertiesPageAddPropertyButtonToolTip); // configure edit button this.btnEditProperty = buttons[1]; this.btnEditProperty.setEnabled(false); this.btnEditProperty.addSelectionListener(new SelectionAdapter() { /** * {@inheritDoc} * * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetSelected( SelectionEvent e ) { handleEditProperty(); } }); this.btnEditProperty.setToolTipText(Messages.propertiesPageEditPropertyButtonToolTip); // configure remove button this.btnRemoveProperty = buttons[2]; this.btnRemoveProperty.setEnabled(false); this.btnRemoveProperty.addSelectionListener(new SelectionAdapter() { /** * {@inheritDoc} * * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent) */ @Override public void widgetSelected( SelectionEvent e ) { handleRemoveProperty(); } }); this.btnRemoveProperty.setToolTipText(Messages.propertiesPageRemovePropertyButtonToolTip); } final Composite finalContainer; CONTAINER: { Composite container = toolkit.createComposite(finalSection); finalContainer = container; container.setLayout(new GridLayout()); container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); finalSection.setClient(container); } VIEWER: { Table table = toolkit.createTable(finalContainer, VIEWER_STYLE); table.setHeaderVisible(true); table.setLinesVisible(true); table.setLayoutData(new GridLayout()); table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); ((GridData)table.getLayoutData()).heightHint = table.getItemHeight() * 5; this.propertyError.setControl(table); this.propertyViewer = new TableViewer(table); this.propertyViewer.setContentProvider(new IStructuredContentProvider() { /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.IContentProvider#dispose() */ @Override public void dispose() { // nothing to do } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.IStructuredContentProvider#getElements(java.lang.Object) */ @Override public Object[] getElements( Object inputElement ) { String metaclass = getSelectedMetaclass(); if (CoreStringUtil.isEmpty(metaclass)) { return ArrayUtil.Constants.EMPTY_ARRAY; } return getMed().getPropertyDefinitions(metaclass).toArray(); } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.IContentProvider#inputChanged(org.eclipse.jface.viewers.Viewer, java.lang.Object, * java.lang.Object) */ @Override public void inputChanged( Viewer viewer, Object oldInput, Object newInput ) { // nothing to do } }); this.propertyViewer.addDoubleClickListener(new IDoubleClickListener() { /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.IDoubleClickListener#doubleClick(org.eclipse.jface.viewers.DoubleClickEvent) */ @Override public void doubleClick( DoubleClickEvent event ) { handleEditProperty(); } }); this.propertyViewer.addSelectionChangedListener(new ISelectionChangedListener() { /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) */ @Override public void selectionChanged( SelectionChangedEvent event ) { handlePropertySelected(); } }); // create table columns TableViewerColumn column = new TableViewerColumn(this.propertyViewer, SWT.LEFT); configureColumn(column, ColumnIndexes.SIMPLE_ID, ColumnHeaders.SIMPLE_ID, ColumnToolTips.SIMPLE_ID, true); column = new TableViewerColumn(this.propertyViewer, SWT.LEFT); configureColumn(column, ColumnIndexes.RUNTIME_TYPE, ColumnHeaders.RUNTIME_TYPE, ColumnToolTips.RUNTIME_TYPE, true); column = new TableViewerColumn(this.propertyViewer, SWT.CENTER); configureColumn(column, ColumnIndexes.REQUIRED, ColumnHeaders.REQUIRED, ColumnToolTips.REQUIRED, false); column = new TableViewerColumn(this.propertyViewer, SWT.CENTER); configureColumn(column, ColumnIndexes.MODIFIABLE, ColumnHeaders.MODFIFIABLE, ColumnToolTips.MODFIFIABLE, false); column = new TableViewerColumn(this.propertyViewer, SWT.CENTER); configureColumn(column, ColumnIndexes.ADVANCED, ColumnHeaders.ADVANCED, ColumnToolTips.ADVANCED, false); column = new TableViewerColumn(this.propertyViewer, SWT.CENTER); configureColumn(column, ColumnIndexes.MASKED, ColumnHeaders.MASKED, ColumnToolTips.MASKED, false); column = new TableViewerColumn(this.propertyViewer, SWT.CENTER); configureColumn(column, ColumnIndexes.INDEXED, ColumnHeaders.INDEXED, ColumnToolTips.INDEXED, false); column = new TableViewerColumn(this.propertyViewer, SWT.LEFT); configureColumn(column, ColumnIndexes.DEFAULT_VALUE, ColumnHeaders.DEFAULT_VALUE, ColumnToolTips.DEFAULT_VALUE, true); column = new TableViewerColumn(this.propertyViewer, SWT.LEFT); configureColumn(column, ColumnIndexes.FIXED_VALUE, ColumnHeaders.FIXED_VALUE, ColumnToolTips.FIXED_VALUE, true); column = new TableViewerColumn(this.propertyViewer, SWT.LEFT); configureColumn(column, ColumnIndexes.ALLOWED_VALUES, ColumnHeaders.ALLOWED_VALUES, ColumnToolTips.ALLOWED_VALUES, true); column = new TableViewerColumn(this.propertyViewer, SWT.LEFT); configureColumn(column, ColumnIndexes.DISPLAY_NAME, ColumnHeaders.DISPLAY_NAME, ColumnToolTips.DISPLAY_NAME, true); column = new TableViewerColumn(this.propertyViewer, SWT.LEFT); configureColumn(column, ColumnIndexes.DESCRIPTION, ColumnHeaders.DESCRIPTION, ColumnToolTips.DESCRIPTION, true); } return finalSection; } Collection<String> getExistingPropertyIds( String metaclassName ) { Collection<ModelExtensionPropertyDefinition> propDefns = getMed().getPropertyDefinitions(metaclassName); if (propDefns == null) { return new ArrayList<String>(0); } Collection<String> result = new ArrayList<String>(propDefns.size()); for (ModelExtensionPropertyDefinition propDefn : propDefns) { result.add(propDefn.getSimpleId()); } return result; } Viewer getMetaclassViewer() { return this.metaclassViewer; } Viewer getPropertyViewer() { return this.propertyViewer; } String getSelectedMetaclass() { IStructuredSelection selection = (IStructuredSelection)this.metaclassViewer.getSelection(); return (selection.isEmpty() ? null : (String)selection.getFirstElement()); } ModelExtensionPropertyDefinition getSelectedProperty() { IStructuredSelection selection = (IStructuredSelection)this.propertyViewer.getSelection(); return (selection.isEmpty() ? null : (ModelExtensionPropertyDefinition)selection.getFirstElement()); } /** * {@inheritDoc} * * @see org.eclipse.ui.part.EditorPart#getTitleToolTip() */ @Override public String getTitleToolTip() { return Messages.medEditorPropertiesPageToolTip; } void handleAddMetaclass() { // Get the metaclass name provider for the med's metamodelUri ExtendableMetaclassNameProvider metaclassNameProvider = ExtensionPlugin.getInstance() .getMetaclassNameProvider(getMed().getMetamodelUri()); if (metaclassNameProvider instanceof ModelTypeMetaclassNameFactory) { metaclassNameProvider = ((ModelTypeMetaclassNameFactory)metaclassNameProvider).getProvider(getMed().getSupportedModelTypes()); } // Current metaclasses extended by the MED List<String> currentlyExtendedMetaclasses = Arrays.asList(getMed().getExtendedMetaclasses()); EditMetaclassDialog dialog = new EditMetaclassDialog(getShell(), metaclassNameProvider, currentlyExtendedMetaclasses); dialog.create(); dialog.getShell().pack(); if (dialog.open() == Window.OK) { String newMetaclassName = dialog.getSelectedMetaclassName(); // select new metaclass if (getMed().addMetaclass(newMetaclassName)) { this.metaclassViewer.setSelection(new StructuredSelection(newMetaclassName)); } } } void handleEditMetaclass() { assert !CoreStringUtil.isEmpty(getSelectedMetaclass()) : "Edit metaclass button is enabled and there is no metaclass selected"; //$NON-NLS-1$ String selectedMetaclassName = getSelectedMetaclass(); // Get the metaclass name provider for the med's metamodelUri String metamodelUri = getMed().getMetamodelUri(); ExtendableMetaclassNameProvider metaclassNameProvider = ExtensionPlugin.getInstance() .getMetaclassNameProvider(metamodelUri); if (metaclassNameProvider instanceof ModelTypeMetaclassNameFactory) { metaclassNameProvider = ((ModelTypeMetaclassNameFactory)metaclassNameProvider).getProvider(getMed().getSupportedModelTypes()); } // Current metaclasses extended by the MED List<String> currentlyExtendedMetaclasses = Arrays.asList(getMed().getExtendedMetaclasses()); EditMetaclassDialog dialog = new EditMetaclassDialog(getShell(), metaclassNameProvider, currentlyExtendedMetaclasses, selectedMetaclassName); dialog.create(); dialog.getShell().pack(); if (dialog.open() == Window.OK) { String modifiedMetaclassName = dialog.getSelectedMetaclassName(); getMed().updateMetaclass(selectedMetaclassName, modifiedMetaclassName); this.metaclassViewer.setSelection(new StructuredSelection(modifiedMetaclassName)); } } void handleAddProperty() { assert (getSelectedMetaclass() != null) : "Selected metaclass is null and shouldn't be"; //$NON-NLS-1$ String metaclassName = getSelectedMetaclass(); EditPropertyDialog dialog = new EditPropertyDialog(getShell(), getMed(), metaclassName, getExistingPropertyIds(metaclassName)); dialog.create(); dialog.getShell().pack(); if (dialog.open() == Window.OK) { ModelExtensionPropertyDefinition newPropDefn = dialog.getPropertyDefinition(); // select new property definition if (getMed().addPropertyDefinition(metaclassName, newPropDefn)) { this.propertyViewer.setSelection(new StructuredSelection(newPropDefn)); } } } void handleEditProperty() { assert !CoreStringUtil.isEmpty(getSelectedMetaclass()) : "Edit property button is enabled and there is no metaclass selected"; //$NON-NLS-1$ assert (getSelectedProperty() != null) : "Edit property button is enabled and there is no property selected"; //$NON-NLS-1$ String metaclassName = getSelectedMetaclass(); ModelExtensionPropertyDefinition selectedPropDefn = getSelectedProperty(); EditPropertyDialog dialog = new EditPropertyDialog(getShell(), getMed(), metaclassName, getExistingPropertyIds(metaclassName), selectedPropDefn); dialog.create(); dialog.getShell().pack(); if (dialog.open() == Window.OK) { ModelExtensionPropertyDefinition modifiedPropDefn = dialog.getPropertyDefinition(); getMed().removePropertyDefinition(metaclassName, selectedPropDefn); getMed().addPropertyDefinition(metaclassName, modifiedPropDefn); } } /** * {@inheritDoc} * * @see org.teiid.designer.extension.ui.editors.MedEditorPage#handleMedReloaded() */ @Override public void handleMedReloaded() { if (this.metaclassViewer != null) { this.metaclassViewer.setInput(this); validateMetaclasses(); } } void handleMetaclassSelected() { boolean enable = (getSelectedMetaclass()!=null && !getMedEditor().isReadOnly()); if (this.btnRemoveMetaclass.getEnabled() != enable) { this.btnRemoveMetaclass.setEnabled(enable); } if (this.btnEditMetaclass.getEnabled() != enable) { this.btnEditMetaclass.setEnabled(enable); } if (this.btnAddProperty.getEnabled() != enable) { this.btnAddProperty.setEnabled(enable); } // alert property viewer the selection changed this.propertyViewer.setInput(this); WidgetUtil.pack(this.propertyViewer); } /** * {@inheritDoc} * * @see org.teiid.designer.extension.ui.editors.MedEditorPage#handlePropertyChanged(java.beans.PropertyChangeEvent) */ @Override protected void handlePropertyChanged( PropertyChangeEvent e ) { // return if GUI hasn't been constructed yet if (this.btnAddMetaclass == null) { return; } String propName = e.getPropertyName(); if (PropertyName.METACLASS.toString().equals(propName)) { validateMetaclasses(); this.metaclassViewer.refresh(); } else if (PropertyName.PROPERTY_DEFINITION.toString().equals(propName)) { validatePropertyDefinitions(); this.propertyViewer.refresh(); } else if (PropertyName.NAMESPACE_PREFIX.toString().equals(propName)) { // changes to MED namespace prefix affect the property definitions namespace prefix validatePropertyDefinitions(); if (this.propertyViewer != null) { this.propertyViewer.refresh(); } } updateState(); } void handlePropertySelected() { boolean enable = (getSelectedProperty()!=null && !getMedEditor().isReadOnly()); if (this.btnRemoveProperty.getEnabled() != enable) { this.btnRemoveProperty.setEnabled(enable); } if (this.btnEditProperty.getEnabled() != enable) { this.btnEditProperty.setEnabled(enable); } } void handleRemoveMetaclass() { assert !CoreStringUtil.isEmpty(getSelectedMetaclass()) : "Remove metaclass button is enabled and there is no metaclass selected"; //$NON-NLS-1$ String selectedMetaclassName = getSelectedMetaclass(); String metaclassShortName = getMetaclassShortName(selectedMetaclassName); if (MessageFormDialog.openQuestion(getShell(), Messages.removeMetaclassDialogTitle, Activator.getDefault().getImage(MED_EDITOR), NLS.bind(Messages.removeMetaclassDialogMsg, metaclassShortName))) { getMed().removeMetaclass(selectedMetaclassName); } } void handleRemoveProperty() { assert !CoreStringUtil.isEmpty(getSelectedMetaclass()) : "Remove property button is enabled and there is no metaclass selected"; //$NON-NLS-1$ assert (getSelectedProperty() != null) : "Remove property button is enabled and there is no property selected"; //$NON-NLS-1$ ModelExtensionPropertyDefinition selectedPropDefn = getSelectedProperty(); if (MessageFormDialog.openQuestion(getShell(), Messages.removePropertyDialogTitle, Activator.getDefault().getImage(MED_EDITOR), NLS.bind(Messages.removePropertyDialogMsg, selectedPropDefn.getSimpleId()))) { getMed().removePropertyDefinition(getSelectedMetaclass(), selectedPropDefn); } } /** * {@inheritDoc} * * @see org.eclipse.ui.forms.editor.FormPage#setFocus() */ @Override public void setFocus() { if (this.metaclassViewer != null) { this.metaclassViewer.getControl().setFocus(); if (this.metaclassViewer.getTable().getItemCount() != 0) { this.metaclassViewer.getTable().select(0); Event event = new Event(); event.widget = this.metaclassViewer.getTable(); this.metaclassViewer.getTable().notifyListeners(SWT.Selection, event); } } else { super.setFocus(); } } /** * {@inheritDoc} * * @see org.teiid.designer.extension.ui.editors.MedEditorPage#setResourceReadOnly(boolean) */ @Override protected void setResourceReadOnly( boolean readOnly ) { updateState(); } /** * {@inheritDoc} * * @see org.teiid.designer.extension.ui.editors.MedEditorPage#updateAllMessages() */ @Override protected void updateAllMessages() { validateMetaclasses(); validatePropertyDefinitions(); } private void updateState() { // return if GUI hasn't been constructed yet if (this.btnAddMetaclass == null) { return; } boolean enable = !getMedEditor().isReadOnly() && !CoreStringUtil.isEmpty(getMed().getMetamodelUri()); if (this.btnAddMetaclass.getEnabled() != enable) { this.btnAddMetaclass.setEnabled(enable); } if (this.btnAddProperty.getEnabled() != enable) { this.btnAddProperty.setEnabled(enable); } if (this.btnEditMetaclass.getEnabled() != enable) { this.btnEditMetaclass.setEnabled(enable); } if (this.btnEditProperty.getEnabled() != enable) { this.btnEditProperty.setEnabled(enable); } if (this.btnRemoveMetaclass.getEnabled() != enable) { this.btnRemoveMetaclass.setEnabled(enable); } if (this.btnRemoveProperty.getEnabled() != enable) { this.btnRemoveProperty.setEnabled(enable); } if (this.propertyViewer.getTable().getEnabled() != enable) { this.propertyViewer.getTable().setEnabled(enable); } handleMetaclassSelected(); handlePropertySelected(); } private void validateMetaclasses() { // Suppress errors on BuiltIns - original built-ins dont fully conform if(getMed().isBuiltIn()) { this.metaclassError.setStatus(ValidationStatus.OK_STATUS); updateMessage(this.metaclassError); validatePropertyDefinitions(); // need to do this to catch when a new metaclass is added return; } final String[] metaclasses = getMed().getExtendedMetaclasses(); // validate with MED validator MedStatus status = ModelExtensionDefinitionValidator.validateMetaclassNames(metaclasses, true); if (!status.isError()) { // validate against metamodel ExtendableMetaclassNameProvider provider = ExtensionPlugin.getInstance().getMetaclassNameProvider(getMed().getMetamodelUri()); if (provider instanceof ModelTypeMetaclassNameFactory) { provider = ((ModelTypeMetaclassNameFactory)provider).getProvider(getMed().getSupportedModelTypes()); } OUTER: for (final String metaclass : metaclasses) { boolean confirmed = false; INNER: for (final String metaclassRoot : provider.getExtendableMetaclassRoots()) { confirmed = confirmMetaclass(metaclass, provider, metaclassRoot); if (confirmed) { break INNER; } } if (!confirmed) { status = ValidationStatus.createErrorMessage(NLS.bind(Messages.metaclassNotFoundByProvider, metaclass)); break OUTER; } } } this.metaclassError.setStatus(status); updateMessage(this.metaclassError); validatePropertyDefinitions(); // need to do this to catch when a new metaclass is added } private void validatePropertyDefinitions() { // Suppress errors on BuiltIns - original built-ins dont fully conform if(getMed().isBuiltIn()) { this.propertyError.setStatus(ValidationStatus.OK_STATUS); } else { this.propertyError.setStatus(ModelExtensionDefinitionValidator.validatePropertyDefinitions(getMed().getPropertyDefinitions())); } updateMessage(this.propertyError); } interface ColumnHeaders { String ADVANCED = Messages.advancedPropertyAttributeColumnHeader; String ALLOWED_VALUES = Messages.allowedValuesPropertyAttributeColumnHeader; String DEFAULT_VALUE = Messages.defaultValuePropertyAttributeColumnHeader; String DESCRIPTION = Messages.descriptionPropertyAttributeColumnHeader; String DISPLAY_NAME = Messages.displayNamePropertyAttributeColumnHeader; String FIXED_VALUE = Messages.fixedValuePropertyAttributeColumnHeader; String INDEXED = Messages.indexedPropertyAttributeColumnHeader; String MASKED = Messages.maskedPropertyAttributeColumnHeader; String MODFIFIABLE = Messages.modifiablePropertyAttributeColumnHeader; String REQUIRED = Messages.requiredPropertyAttributeColumnHeader; String RUNTIME_TYPE = Messages.runtimeTypePropertyAttributeColumnHeader; String SIMPLE_ID = Messages.simpleIdPropertyAttributeColumnHeader; } interface ColumnIndexes { int SIMPLE_ID = 0; int RUNTIME_TYPE = 1; int REQUIRED = 2; int MODIFIABLE = 3; int ADVANCED = 4; int MASKED = 5; int INDEXED = 6; int DEFAULT_VALUE = 7; int FIXED_VALUE = 8; int ALLOWED_VALUES = 9; int DISPLAY_NAME = 10; int DESCRIPTION = 11; } interface ColumnToolTips { String ADVANCED = Messages.advancedPropertyAttributeColumnHeaderToolTip; String ALLOWED_VALUES = Messages.allowedValuesPropertyAttributeColumnHeaderToolTip; String DEFAULT_VALUE = Messages.defaultValuePropertyAttributeColumnHeaderToolTip; String DESCRIPTION = Messages.descriptionPropertyAttributeColumnHeaderToolTip; String DISPLAY_NAME = Messages.displayNamePropertyAttributeColumnHeaderToolTip; String FIXED_VALUE = Messages.fixedValuePropertyAttributeColumnHeaderToolTip; String INDEXED = Messages.indexedPropertyAttributeColumnHeaderToolTip; String MASKED = Messages.maskedPropertyAttributeColumnHeaderToolTip; String MODFIFIABLE = Messages.modifiablePropertyAttributeColumnHeaderToolTip; String REQUIRED = Messages.requiredPropertyAttributeColumnHeaderToolTip; String RUNTIME_TYPE = Messages.runtimeTypePropertyAttributeColumnHeaderToolTip; String SIMPLE_ID = Messages.simpleIdPropertyAttributeColumnHeaderToolTip; } class PropertyLabelProvider extends ColumnLabelProvider { private final int columnIndex; public PropertyLabelProvider( final int columnIndex ) { this.columnIndex = columnIndex; } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.ColumnLabelProvider#getImage(java.lang.Object) */ @Override public Image getImage( Object element ) { ModelExtensionPropertyDefinition propDefn = (ModelExtensionPropertyDefinition)element; boolean enabled = false; if ((ColumnIndexes.ADVANCED == this.columnIndex) && propDefn.isAdvanced()) { enabled = true; } else if ((ColumnIndexes.INDEXED == this.columnIndex) && propDefn.shouldBeIndexed()) { enabled = true; } else if ((ColumnIndexes.MASKED == this.columnIndex) && propDefn.isMasked()) { enabled = true; } else if ((ColumnIndexes.MODIFIABLE == this.columnIndex) && propDefn.isModifiable()) { enabled = true; } else if ((ColumnIndexes.REQUIRED == this.columnIndex) && propDefn.isRequired()) { enabled = true; } return (enabled ? Activator.getDefault().getImage(CHECK_MARK) : null); } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.ColumnLabelProvider#getText(java.lang.Object) */ @Override public String getText( Object element ) { ModelExtensionPropertyDefinition propDefn = (ModelExtensionPropertyDefinition)element; if (ColumnIndexes.SIMPLE_ID == this.columnIndex) { return propDefn.getSimpleId(); } if (ColumnIndexes.DEFAULT_VALUE == this.columnIndex) { return propDefn.getDefaultValue(); } if (ColumnIndexes.FIXED_VALUE == this.columnIndex) { return propDefn.getFixedValue(); } if (ColumnIndexes.DESCRIPTION == this.columnIndex) { String description = propDefn.getDescription(); if (CoreStringUtil.isEmpty(description)) { int size = propDefn.getDescriptions().size(); if (size == 1) { return Messages.propertiesPageOneTranslationAvailable; } if (size != 0) { return NLS.bind(Messages.propertiesPageManyTranslationsAvailable, size); } return CoreStringUtil.Constants.EMPTY_STRING; } return description; } if (ColumnIndexes.RUNTIME_TYPE == this.columnIndex) { return propDefn.getRuntimeType(); } if (ColumnIndexes.DISPLAY_NAME == this.columnIndex) { String displayName = propDefn.getDisplayName(); if (CoreStringUtil.isEmpty(displayName)) { int size = propDefn.getDisplayNames().size(); if (size == 1) { return Messages.propertiesPageOneTranslationAvailable; } if (size != 0) { return NLS.bind(Messages.propertiesPageManyTranslationsAvailable, size); } return CoreStringUtil.Constants.EMPTY_STRING; } return displayName; } if (ColumnIndexes.ALLOWED_VALUES == this.columnIndex) { String[] allowedValues = propDefn.getAllowedValues(); if ((allowedValues != null) && (allowedValues.length != 0)) { StringBuilder txt = new StringBuilder(); for (int size = allowedValues.length, i = 0; i < size; ++i) { if (i != 0) { txt.append(","); //$NON-NLS-1$ } txt.append(allowedValues[i]); } return txt.toString(); } } // don't return a value for the boolean columns return null; } } class SelectionProvider implements MedSelectionProvider { private final List<ISelectionChangedListener> listeners; private final boolean metaclassViewerFlag; public SelectionProvider( boolean metaclassViewerFlag ) { Viewer viewer = (metaclassViewerFlag ? getMetaclassViewer() : getPropertyViewer()); viewer.addSelectionChangedListener(new ISelectionChangedListener() { /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent) */ @Override public void selectionChanged( SelectionChangedEvent event ) { fireSelectionChanged(event); } }); this.metaclassViewerFlag = metaclassViewerFlag; this.listeners = new ArrayList<ISelectionChangedListener>(1); // should only be synchronizer } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.ISelectionProvider#addSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener) */ @Override public void addSelectionChangedListener( ISelectionChangedListener listener ) { if (!this.listeners.contains(listener)) { this.listeners.add(listener); } } void fireSelectionChanged( SelectionChangedEvent viewerEvent ) { IStructuredSelection viewerSelection = (IStructuredSelection)viewerEvent.getSelection(); if (!viewerSelection.isEmpty()) { MedSelectionSynchronizer selectionSynchronizer = getMedEditor().getSelectionSynchronizer(); MedModelNode modelNode = null; if (this.metaclassViewerFlag) { modelNode = selectionSynchronizer.getMetaclassNode(getSelectedMetaclass()); } else { modelNode = selectionSynchronizer.getPropertyDefinitionNode(getSelectedMetaclass(), getSelectedProperty()); } SelectionChangedEvent event = new SelectionChangedEvent(this, new StructuredSelection(modelNode)); for (ISelectionChangedListener listener : this.listeners) { listener.selectionChanged(event); } } } /** * {@inheritDoc} * * @see org.teiid.designer.extension.ui.editors.MedSelectionProvider#getMedEditorPage() */ @Override public MedEditorPage getMedEditorPage() { return accessPage(); } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.ISelectionProvider#getSelection() */ @Override public ISelection getSelection() { MedSelectionSynchronizer selectionSynchronizer = getMedEditor().getSelectionSynchronizer(); // if metaclass need to convert metaclass string to node if (this.metaclassViewerFlag) { String metaclass = getSelectedMetaclass(); if (metaclass != null) { MedModelNode metaclassNode = selectionSynchronizer.getMetaclassNode(metaclass); if (metaclassNode != null) { return new StructuredSelection(metaclassNode); } } } else { // need to convert propDefn to node ModelExtensionPropertyDefinition propDefn = getSelectedProperty(); if (propDefn != null) { MedModelNode propDefnNode = selectionSynchronizer.getPropertyDefinitionNode(getSelectedMetaclass(), propDefn); if (propDefnNode != null) { return new StructuredSelection(propDefnNode); } } } return StructuredSelection.EMPTY; } /** * {@inheritDoc} * * @see org.teiid.designer.extension.ui.editors.MedSelectionProvider#getSelectedNode(org.teiid.designer.extension.ui.model.MedModelNode.ModelType) */ @Override public MedModelNode getSelectedNode( ModelType type ) { IStructuredSelection selection = (IStructuredSelection)getSelection(); if (!selection.isEmpty()) { String metaclass = getSelectedMetaclass(); if (ModelType.METACLASS == type) { return getMedEditor().getSelectionSynchronizer().getMetaclassNode(metaclass); } if (!this.metaclassViewerFlag && (ModelType.PROPERTY_DEFINITION == type)) { ModelExtensionPropertyDefinition propDefn = getSelectedProperty(); return getMedEditor().getSelectionSynchronizer().getPropertyDefinitionNode(metaclass, propDefn); } } return null; } /** * {@inheritDoc} * * @see org.teiid.designer.extension.ui.editors.MedSelectionProvider#isApplicable(org.eclipse.jface.viewers.IStructuredSelection) */ @Override public boolean isApplicable( IStructuredSelection selection ) { if (!selection.isEmpty()) { MedModelNode modelNode = (MedModelNode)selection.getFirstElement(); if (ModelType.METACLASS == modelNode.getType()) { return this.metaclassViewerFlag; } if (ModelType.PROPERTY_DEFINITION == modelNode.getType()) { return !this.metaclassViewerFlag; } } return false; } /** * {@inheritDoc} * * @see org.teiid.designer.extension.ui.editors.MedSelectionProvider#refresh() */ @Override public void refresh() { Viewer viewer = (this.metaclassViewerFlag ? getMetaclassViewer() : getPropertyViewer()); viewer.refresh(); } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.ISelectionProvider#removeSelectionChangedListener(org.eclipse.jface.viewers.ISelectionChangedListener) */ @Override public void removeSelectionChangedListener( ISelectionChangedListener listener ) { this.listeners.remove(listener); } /** * {@inheritDoc} * * @see org.eclipse.jface.viewers.ISelectionProvider#setSelection(org.eclipse.jface.viewers.ISelection) */ @Override public void setSelection( ISelection selection ) { if (!selection.isEmpty() && (selection instanceof IStructuredSelection)) { MedModelNode modelNode = (MedModelNode)((IStructuredSelection)selection).getFirstElement(); if (!this.metaclassViewerFlag && (ModelType.PROPERTY_DEFINITION == modelNode.getType())) { // make sure metaclass is selected first IStructuredSelection metaclassSelection = new StructuredSelection(modelNode.getMetaclass()); if (!metaclassSelection.equals(getMetaclassViewer().getSelection())) { getMetaclassViewer().setSelection(metaclassSelection, true); } // select prop defn IStructuredSelection propertySelection = new StructuredSelection(modelNode.getPropertyDefinition()); if (!propertySelection.equals(getPropertyViewer().getSelection())) { getPropertyViewer().setSelection(propertySelection, true); } ensureVisible(getPropertyViewer().getControl()); } else if (ModelType.METACLASS == modelNode.getType()) { IStructuredSelection metaclassSelection = new StructuredSelection(modelNode.getMetaclass()); if (this.metaclassViewerFlag) { if (!metaclassSelection.equals(getMetaclassViewer().getSelection())) { getMetaclassViewer().setSelection(metaclassSelection, true); } ensureVisible(getMetaclassViewer().getControl().getParent()); } } } } } }