/*****************************************************************************
* Copyright (c) 2011 LIFL & CEA LIST.
*
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Cedric Dumoulin (LIFL) cedric.dumoulin@lifl.fr - Initial API and implementation
* Vincent Lorenzo (CEA-LIST) vincent.lorenzo@cea.fr
*****************************************************************************/
package org.eclipse.papyrus.infra.table.common.handlers;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import org.eclipse.core.commands.AbstractHandler;
import org.eclipse.core.commands.ExecutionEvent;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.facet.infra.query.ModelQuery;
import org.eclipse.emf.facet.infra.query.ModelQuerySet;
import org.eclipse.emf.facet.infra.query.core.AbstractModelQuery;
import org.eclipse.emf.facet.infra.query.core.ModelQuerySetCatalog;
import org.eclipse.emf.facet.infra.query.core.exception.ModelQueryException;
import org.eclipse.emf.facet.infra.query.runtime.ModelQueryResult;
import org.eclipse.emf.facet.widgets.nattable.NatTableWidgetUtils;
import org.eclipse.emf.facet.widgets.nattable.instance.tableinstance.Column;
import org.eclipse.emf.facet.widgets.nattable.instance.tableinstance2.TableInstance2;
import org.eclipse.emf.facet.widgets.nattable.internal.NatTableWidgetInternalUtils;
import org.eclipse.emf.facet.widgets.nattable.tableconfiguration.TableConfiguration;
import org.eclipse.emf.facet.widgets.nattable.tableconfiguration2.TableConfiguration2;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.workspace.AbstractEMFOperation;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.papyrus.commands.CheckedOperationHistory;
import org.eclipse.papyrus.infra.core.editor.BackboneException;
import org.eclipse.papyrus.infra.core.editor.IMultiDiagramEditor;
import org.eclipse.papyrus.infra.core.resource.AbstractBaseModel;
import org.eclipse.papyrus.infra.core.resource.IModel;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
import org.eclipse.papyrus.infra.core.resource.NotFoundException;
import org.eclipse.papyrus.infra.core.sasheditor.contentprovider.IPageMngr;
import org.eclipse.papyrus.infra.core.services.ServiceException;
import org.eclipse.papyrus.infra.core.services.ServicesRegistry;
import org.eclipse.papyrus.infra.core.utils.EditorUtils;
import org.eclipse.papyrus.infra.core.utils.ServiceUtils;
import org.eclipse.papyrus.infra.core.utils.ServiceUtilsForActionHandlers;
import org.eclipse.papyrus.infra.table.common.Activator;
import org.eclipse.papyrus.infra.table.common.dialog.TwoInputDialog;
import org.eclipse.papyrus.infra.table.common.messages.Messages;
import org.eclipse.papyrus.infra.table.common.modelresource.EMFFacetNattableModel;
import org.eclipse.papyrus.infra.table.common.modelresource.PapyrusNattableModel;
import org.eclipse.papyrus.infra.table.common.util.QueryRepresentation;
import org.eclipse.papyrus.infra.table.instance.papyrustableinstance.PapyrusTableInstance;
import org.eclipse.papyrus.infra.table.instance.papyrustableinstance.PapyrustableinstanceFactory;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.uml2.uml.Element;
/**
* @author dumoulin
*
*/
public abstract class AbstractCreateNattableEditorCommand extends AbstractHandler {
/** the default name for the table */
private final String defaultName;
/** the default description for the table */
private final String defaultDescription = "Table Description"; //$NON-NLS-1$
/** the description for the table */
private String description;
/** the name for the table */
private String name;
/** the editor type */
private final String editorType;
/**
*
* Constructor.
*
* @param editorType
* the type of the editor
* @param defaultName
* the default name for this editor
*/
public AbstractCreateNattableEditorCommand(final String editorType, final String defaultName) {
Assert.isNotNull(editorType != null);
this.editorType = editorType;
this.defaultName = defaultName;
}
/**
* Should be overridden in order to restrict creation
*
* @see org.eclipse.core.commands.AbstractHandler#isEnabled()
*
* @return
*/
@Override
public boolean isEnabled() {
EObject context = getTableContext();
return context instanceof Element;
}
/**
* @see org.eclipse.core.commands.IHandler#execute(org.eclipse.core.commands.ExecutionEvent)
*
* @param event
* @return
* @throws ExecutionException
*/
public Object execute(final ExecutionEvent event) throws ExecutionException {
try {
runAsTransaction();
} catch (ServiceException e) {
throw new ExecutionException("Can't create TableEditor", e); //$NON-NLS-1$
}
return null;
}
/**
* Run the command as a transaction.
* Create a Transaction and delegate the command to {@link #doExecute(ServicesRegistry)}.
*
* @throws ServiceException
*
*/
public void runAsTransaction() throws ServiceException {
//default Value
name = defaultName;
description = defaultDescription;
TwoInputDialog dialog = new TwoInputDialog(Display.getCurrent().getActiveShell(), Messages.AbstractCreateNattableEditorCommand_CreateNewTableDialogTitle, Messages.AbstractCreateNattableEditorCommand_CreateNewTableDialog_TableNameMessage, Messages.AbstractCreateNattableEditorCommand_CreateNewTableDialog_TableDescriptionMessage, defaultName, defaultDescription, null);
if(dialog.open() == Dialog.OK) {
//get the name and the description for the table
name = dialog.getValue();
description = dialog.getValue_2();
final ServicesRegistry serviceRegistry = ServiceUtilsForActionHandlers.getInstance().getServiceRegistry();
TransactionalEditingDomain domain = ServiceUtils.getInstance().getTransactionalEditingDomain(serviceRegistry);
//Create the transactional command
AbstractEMFOperation command = new AbstractEMFOperation(domain, "Create Table Editor") { //$NON-NLS-1$
@Override
protected IStatus doExecute(final IProgressMonitor monitor, final IAdaptable info) throws ExecutionException {
try {
AbstractCreateNattableEditorCommand.this.doExecute(serviceRegistry);
} catch (ServiceException e) {
e.printStackTrace();
return Status.CANCEL_STATUS;
} catch (NotFoundException e) {
e.printStackTrace();
return Status.CANCEL_STATUS;
}
return Status.OK_STATUS;
}
};
// Execute the command
try {
CheckedOperationHistory.getInstance().execute(command, new NullProgressMonitor(), null);
} catch (ExecutionException e) {
Activator.getDefault().log.error("Can't create Table Editor", e); //$NON-NLS-1$
}
}
}
/**
* Do the execution of the command.
*
* @param serviceRegistry
* @throws ServiceException
* @throws NotFoundException
*/
public void doExecute(final ServicesRegistry serviceRegistry) throws ServiceException, NotFoundException {
Object editorModel = createEditorModel(serviceRegistry);
// Get the mngr allowing to add/open new editor.
IPageMngr pageMngr = ServiceUtils.getInstance().getIPageMngr(serviceRegistry);
// add the new editor model to the sash.
pageMngr.openPage(editorModel);
}
/**
* Create a model identifying the editor. This model will be saved with the sash
*
* @return
* @throws ServiceException
* @throws NotFoundException
* The model where to save the TableInstance is not found.
*/
protected Object createEditorModel(final ServicesRegistry serviceRegistry) throws ServiceException, NotFoundException {
PapyrusTableInstance papyrusTable = PapyrustableinstanceFactory.eINSTANCE.createPapyrusTableInstance();
papyrusTable.setName(name);
papyrusTable.setType(editorType);
PapyrusNattableModel papyrusModel = (PapyrusNattableModel)ServiceUtils.getInstance().getModelSet(serviceRegistry).getModelChecked(PapyrusNattableModel.MODEL_ID);
papyrusModel.addPapyrusTableInstance(papyrusTable);
setFillingQueries(papyrusTable); //should be done before the TableInstance creation
setSynchronization(papyrusTable); //should be done before the TableInstance creation
EObject context = getTableContext();
Assert.isNotNull(context);
List<EObject> elements = getInitialElement(papyrusTable, context);
TableInstance2 tableInstance = NatTableWidgetUtils.createTableInstance(elements, defaultDescription, getTableConfiguration2(), getTableContext(), null);
tableInstance.setDescription(description);
// Save the model in the associated resource
EMFFacetNattableModel model = (EMFFacetNattableModel)ServiceUtils.getInstance().getModelSet(serviceRegistry).getModelChecked(EMFFacetNattableModel.MODEL_ID);
model.addTableInstance(tableInstance);
papyrusTable.setTable(tableInstance);
tableInstance.setContext(context);
setHiddenColumns(papyrusTable);
return papyrusTable;
}
/**
*
* @param papyrusTable
* the papyrus table
* @param context
* @return the list of the initial element for the table
*/
private List<EObject> getInitialElement(PapyrusTableInstance papyrusTable, EObject context) {
if(papyrusTable.isIsSynchronized() && !papyrusTable.getFillingQueries().isEmpty()) {
List<EObject> elements = new ArrayList<EObject>();
for(ModelQuery query : papyrusTable.getFillingQueries()) {
ModelQuerySetCatalog catalog = ModelQuerySetCatalog.getSingleton();
AbstractModelQuery impl = null;
try {
impl = catalog.getModelQueryImpl(query);
} catch (ModelQueryException e) {
Activator.getDefault().log.error(e);
}
if(impl != null) {
ModelQueryResult result = impl.evaluate(context);
Object value = result.getValue();
if(value instanceof Collection<?>) {
// the build the list of the elements to add in the
// table
for(Object currentObject : (Collection<?>)value) {
if(currentObject instanceof EObject) {
elements.add((EObject)currentObject);
}
}
}
}
}
return elements;
}
return Collections.emptyList();
}
/**
* Allows to hide the columns created by default
*
* @param papyrusTable
*/
private void setHiddenColumns(final PapyrusTableInstance papyrusTable) {
List<String> hiddenColumnsName = getHiddenColumnName();
if(!hiddenColumnsName.isEmpty()) {
for(Column column : papyrusTable.getTable().getColumns()) {
String name = NatTableWidgetInternalUtils.getColumnName(column);
if(hiddenColumnsName.contains(name)) {
column.setIsHidden(true);
}
}
}
}
/**
* Returns the list of the columns to hide. Currently, the name can be :
* <ul>
* <li>[Label]</li>
* <li>[Metaclass]</li>
* <li>/eContainer</li>
* </ul>
*
* @return
* the list of the columns to hide
*/
protected List<String> getHiddenColumnName() {
return Collections.emptyList();
}
/**
* Returns the table configuration for the table
*
* {@link Deprecated} // use getTableConfiguration2
*
* @return
* the table configuration of the table
* FIXME should be removed in Papyrus 0.9.0
*
*/
@Deprecated
protected TableConfiguration getTableConfiguration() {
return getTableConfiguration2();
}
/**
* Returns the table configuration for the table
*
* @return
* the table configuration of the table
*
*/
protected TableConfiguration2 getTableConfiguration2() {
return null;
}
/**
* Set the table synchronization to <code>true</code> if there is filling queries, to <code>false</code> if not
*
* @param papyrusTable
* the papyrusTable
*/
protected void setSynchronization(final PapyrusTableInstance papyrusTable) {
papyrusTable.setIsSynchronized(papyrusTable.getFillingQueries().size() != 0);
}
/**
* Set the queries used to fill Papyrus
*
* @param papyrusTable
* the {@link PapyrusTableInstance} to fill with queries
*/
protected void setFillingQueries(final PapyrusTableInstance papyrusTable) {
ModelQuerySetCatalog catalog = ModelQuerySetCatalog.getSingleton();
for(QueryRepresentation rep : getQueryRepresentations()) {
ModelQuerySet querySet = catalog.getModelQuerySet(rep.getQuerySetName());
if(querySet != null) {
ModelQuery query = querySet.getQuery(rep.getQueryName());
if(query != null) {
papyrusTable.getFillingQueries().add(query);
}
}
}
}
/**
* Get the current MultiDiagramEditor.
*
* @return
* @throws BackboneException
*/
protected IMultiDiagramEditor getMultiDiagramEditor() throws BackboneException {
return EditorUtils.getMultiDiagramEditorChecked();
}
/**
* Returns the context used to create the table
*
* @return
* the context used to create the table or <code>null</code> if not found
* @throws ServiceException
*/
protected EObject getTableContext() {
List<EObject> selection = getSelection();
if(!selection.isEmpty()) {
return selection.get(0);
}
//we shouldn't try to find a valid context when the selection is not valid!
ModelSet modelSet = null;
ServicesRegistry serviceRegistry;
try {
serviceRegistry = ServiceUtilsForActionHandlers.getInstance().getServiceRegistry();
modelSet = ServiceUtils.getInstance().getModelSet(serviceRegistry);
} catch (NullPointerException npe) {
//
} catch (ServiceException exception) {
}
if(modelSet != null) {
IModel model = modelSet.getModel(org.eclipse.papyrus.infra.core.resource.uml.UmlModel.MODEL_ID);
if(model instanceof AbstractBaseModel) {
return getRootElement(((AbstractBaseModel)model).getResource());
}
}
return null;
}
/**
*
* @return
*/
protected List<EObject> getSelection() {
List<EObject> selectedElements = new ArrayList<EObject>();
ISelection selection = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getSelectionService().getSelection();
if(selection instanceof IStructuredSelection) {
IStructuredSelection structuredSelection = (IStructuredSelection)selection;
Iterator<?> it = structuredSelection.iterator();
while(it.hasNext()) {
Object object = it.next();
if(object instanceof IAdaptable) {
EObject currentEObject = (EObject)((IAdaptable)object).getAdapter(EObject.class);
if(currentEObject != null) {
selectedElements.add(currentEObject);
}
}
}
}
return selectedElements;
}
/**
* Get the root element associated with canvas.
*/
protected EObject getRootElement(final Resource modelResource) {
EObject rootElement = null;
if(modelResource != null && modelResource.getContents() != null && modelResource.getContents().size() > 0) {
Object root = modelResource.getContents().get(0);
if(root instanceof EObject) {
rootElement = (EObject)root;
}
}
return rootElement;
}
/**
* This method should be overridden by the user, if he wants provide filling queries
* The list of the queries used to fill the table, identified by their querySet name and query name.
*
*
* @return
* The list of the queries used to fill the table, identified by their querySet name and query name.
*
*/
protected List<QueryRepresentation> getQueryRepresentations() {
List<QueryRepresentation> list = new ArrayList<QueryRepresentation>();
return list;
}
}