/**
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright (C) 2007 Ronny Brandt (Ronny_Brandt@web.de). *
* All rights reserved. *
* *
* This work was done as a project at the Chair for Software Technology, *
* Dresden University Of Technology, Germany (http://st.inf.tu-dresden.de). *
* It is understood that any modification not identified as such is not *
* covered by the preceding statement. *
* *
* This work is free software; you can redistribute it and/or modify it *
* under the terms of the GNU Library General Public License as published *
* by the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This work is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public *
* License for more details. *
* *
* You should have received a copy of the GNU Library General Public License *
* along with this library; if not, you can view it online at *
* http://www.fsf.org/licensing/licenses/gpl.html. *
* *
* To submit a bug report, send a comment, or get the latest news on this *
* project, please visit the website: http://dresden-ocl.sourceforge.net. *
* For more information on OCL and related projects visit the OCL Portal: *
* http://st.inf.tu-dresden.de/ocl *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
package org.dresdenocl.interpreter.ui.internal.views;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import org.dresdenocl.interpreter.IInterpretationResult;
import org.dresdenocl.interpreter.IOclInterpreter;
import org.dresdenocl.interpreter.OclInterpreterPlugin;
import org.dresdenocl.interpreter.event.IInterpreterRegistryListener;
import org.dresdenocl.interpreter.event.internal.InterpreterRegistryEvent;
import org.dresdenocl.interpreter.ui.internal.msg.OclInterpreterUIMessages;
import org.dresdenocl.interpreter.ui.internal.views.util.ResultsContentProvider;
import org.dresdenocl.interpreter.ui.internal.views.util.ResultsFilter;
import org.dresdenocl.interpreter.ui.internal.views.util.ResultsLabelProvider;
import org.dresdenocl.model.event.IModelRegistryListener;
import org.dresdenocl.model.event.ModelRegistryEvent;
import org.dresdenocl.modelbus.IModelBusConstants;
import org.dresdenocl.modelbus.ModelBusPlugin;
import org.dresdenocl.modelbus.ui.ModelBusUIPlugin;
import org.dresdenocl.modelinstance.IModelInstance;
import org.dresdenocl.modelinstance.event.IModelInstanceRegistryListener;
import org.dresdenocl.modelinstance.event.ModelInstanceRegistryEvent;
import org.dresdenocl.modelinstancetype.types.IModelInstanceElement;
import org.dresdenocl.pivotmodel.Constraint;
import org.dresdenocl.pivotmodel.Type;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TreeSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.ISelectionService;
import org.eclipse.ui.IViewActionDelegate;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.part.ViewPart;
/**
* <p>
* This class provides the view which is used to present the results of the
* {@link IOclInterpreter}.
* </p>
*
* @author Ronny Brandt
*/
public class InterpreterView extends ViewPart implements ISelectionListener,
IModelInstanceRegistryListener, IModelRegistryListener,
IInterpreterRegistryListener {
/** Icon to add variables to the environment. */
public static String ADD_IMAGE = "icons/add.gif";
/** Icon to add variables to the environment. */
public static String INTERPRET_IMAGE = "icons/interpret.gif";
/** Icon to add variables to the environment. */
public static String PREPARE_IMAGE = "icons/prepare.gif";
/** Icon to remove the interpretation results. */
public static String REMOVE_IMAGE = "icons/remove.gif";
/** The currently selected {@link Constraint}s that shall be interpreted. */
private final Set<Constraint> currentlySelectedConstraints = new HashSet<Constraint>();
/** The currently selected {@link IModelInstance}. */
private IModelInstance currentlySelectedModelInstance;
/**
* The currently selected {@link IModelInstanceElement}s that shall be
* interpreted.
*/
private final Set<IModelInstanceElement> currentlySelectedModelInstanceElements = new HashSet<IModelInstanceElement>();
/** The currently selected rows of this {@link IViewActionDelegate}. */
private final Set<Object[]> currentlySelectedRows = new HashSet<Object[]>();
/**
* A {@link Map} containing the {@link IOclInterpreter}s for all
* {@link IModelInstance}s. <b>This is a {@link WeakHashMap}!</b> The
* {@link IOclInterpreter}s for {@link IModelInstance}s that are not
* referenced anymore will be collected by the garbage collector!
*/
private Map<IModelInstance, IOclInterpreter> myCachedInterpreters = new WeakHashMap<IModelInstance, IOclInterpreter>();
/** The currently selected {@link ResultFilter}. */
private ResultsFilter myCurrentFilter = new ResultsFilter(this);
/** The {@link InterpretationResultCache} of this {@link InterpreterView}. */
private InterpretationResultCache myResults = new InterpretationResultCache();
/**
* The {@link TableViewer} used to present the results of the
* interpretation.
*/
private TableViewer myTableViewer;
/**
* <p>
* Creates a new {@link InterpreterView}.
* </p>
*/
public InterpreterView() {
/* Register this view as a model listener. */
ModelBusPlugin.getModelRegistry().addModelRegistryListener(this);
/* Register this view as a model instance listener. */
ModelBusPlugin.getModelInstanceRegistry()
.addModelInstanceRegistryListener(this);
this.currentlySelectedModelInstance = ModelBusPlugin
.getModelInstanceRegistry().getActiveModelInstance(
ModelBusPlugin.getModelRegistry().getActiveModel());
OclInterpreterPlugin.getInterpreterRegistry()
.addInterpreterRegistryListener(this);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.ui.part.WorkbenchPart#dispose()
*/
public void dispose() {
try {
// Remove this view as listener of related plug-ins.
ModelBusPlugin.getModelRegistry().removeModelRegistryListener(this);
ModelBusPlugin.getModelInstanceRegistry()
.removeModelInstanceRegistryListener(this);
((ISelectionService) getSite().getService(ISelectionService.class))
.removeSelectionListener(this);
OclInterpreterPlugin.getInterpreterRegistry()
.removeInterpreterRegistryListener(this);
} finally {
super.dispose();
}
}
/*
* (non-Javadoc)
*
* @seeorg.dresdenocl.modelbus.event.IModelRegistryListener#
* activeModelChanged (org.dresdenocl.modelbus.event.ModelRegistryEvent)
*/
public void activeModelChanged(ModelRegistryEvent event) {
this.myResults.clear();
}
/*
* (non-Javadoc)
*
* @seeorg.dresdenocl.modelbus.event.IModelInstanceRegistryListener#
* activeModelInstanceChanged
* (org.dresdenocl.modelbus.event.ModelInstanceRegistryEvent)
*/
public void activeModelInstanceChanged(ModelInstanceRegistryEvent event) {
this.currentlySelectedModelInstance = ModelBusPlugin
.getModelInstanceRegistry().getActiveModelInstance(
ModelBusPlugin.getModelRegistry().getActiveModel());
this.myResults.clear();
}
/**
* <p>
* Called to create and initialize the {@link InterpreterView}.
* </p>
*
* @param parent
* The parent composite of the created {@link TableViewer}.
*/
public void createPartControl(Composite parent) {
final Table table;
TableColumn column;
this.myTableViewer = new TableViewer(parent, SWT.MULTI | SWT.H_SCROLL
| SWT.V_SCROLL);
/* Set the content and label provider. */
this.myTableViewer.setContentProvider(new ResultsContentProvider());
this.myTableViewer.setLabelProvider(new ResultsLabelProvider());
table = myTableViewer.getTable();
table.setLayoutData(new GridData(GridData.FILL_BOTH));
table.setHeaderVisible(true);
table.setLinesVisible(true);
/* Initialize the columns of the table. */
column = new TableColumn(table, SWT.LEFT);
column.setText(OclInterpreterUIMessages.InterpreterView_ObjectColumn);
column = new TableColumn(table, SWT.LEFT);
column.setText(OclInterpreterUIMessages.InterpreterView_ConstraintColumn);
column = new TableColumn(table, SWT.LEFT);
column.setText(OclInterpreterUIMessages.InterpreterView_ResultColumn);
this.myTableViewer.setInput(this.myResults);
this.refreshView();
this.getViewSite().getPage().addSelectionListener(this);
this.getViewSite().setSelectionProvider(this.myTableViewer);
// this.initMenu();
}
/*
* (non-Javadoc)
*
* @see org.dresdenocl.modelbus.event.IModelRegistryListener#modelAdded
* (org.dresdenocl.modelbus.event.ModelRegistryEvent)
*/
public void modelAdded(ModelRegistryEvent event) {
/* Do nothing until a new active IModel has been set. */
}
public void modelRemoved(ModelRegistryEvent event) {
/* Do nothing until a new active IModel has been set. */
}
/*
* (non-Javadoc)
*
* @seeorg.dresdenocl.modelbus.event.IModelInstanceRegistryListener#
* modelInstanceAdded
* (org.dresdenocl.modelbus.event.ModelInstanceRegistryEvent)
*/
public void modelInstanceAdded(ModelInstanceRegistryEvent event) {
/* Do nothing until a new ModelInstance has been activated. */
}
public void modelInstanceRemoved(ModelInstanceRegistryEvent event) {
/* Do nothing until a new ModelInstance has been activated. */
}
/*
* (non-Javadoc)
*
* @seeorg.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.
* IWorkbenchPart, org.eclipse.jface.viewers.ISelection)
*/
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
/* Check if the selection of the models view changed. */
if (part.getSite() != null
&& part.getSite().getId()
.equals(IModelBusConstants.MODELS_VIEW_ID)) {
/* Check if the selection is a tree selection. */
if (selection instanceof TreeSelection) {
/* Get an iterator to iterate over the selection. */
Iterator<?> selectionIt;
selectionIt = ((TreeSelection) selection).iterator();
/* Remove the current filter from the table viewer. */
this.myTableViewer.removeFilter(this.myCurrentFilter);
/* Clear the currently selected constraints and model objects. */
this.clearConstraintSelection();
this.clearModelObjectSelection();
/*
* Add all selected constraints and types to the constraint
* selection.
*/
while (selectionIt.hasNext()) {
Object anObject;
anObject = selectionIt.next();
if (anObject instanceof Constraint) {
this.addConstraintSelection((Constraint) anObject);
}
else if (anObject instanceof Type) {
this.addModelObjectSelection((Type) anObject);
}
// no else.
}
// end while.
/* Read the filter to the table viewer. */
this.myTableViewer.addFilter(this.myCurrentFilter);
this.refreshView();
}
// no else (no tree selection, could not happen).
}
/* Else check if the selection of the model instance view changed. */
else if (part.getSite() != null
&& part.getSite().getId()
.equals(IModelBusConstants.MODEL_INSTANCES_VIEW_ID)) {
/* Check if the selection is a tree selection. */
if (selection instanceof TreeSelection) {
/* Get an iterator to iterate over the selection. */
Iterator<?> selectionIt;
selectionIt = ((TreeSelection) selection).iterator();
/* Remove the current filter from the table viewer. */
this.myTableViewer.removeFilter(this.myCurrentFilter);
/* Clear the currently selected model objects. */
this.clearModelObjectSelection();
/* Add all selected IModelObjects to the current selection. */
while (selectionIt.hasNext()) {
Object anObject;
anObject = selectionIt.next();
/* Decide between given Types and IModelObjects. */
if (anObject instanceof IModelInstanceElement) {
this.addModelObjectSelection((IModelInstanceElement) anObject);
}
else if (anObject instanceof Type) {
this.addModelObjectSelection((Type) anObject);
}
}
// end while.
/* Readd the filter to the table viewer. */
this.myTableViewer.addFilter(myCurrentFilter);
this.refreshView();
}
// no else (no tree selection, could not happen).
}
/* Else check if the selection of the interpreter view changed. */
else if (part instanceof InterpreterView) {
/* Check if the selection is a structured selection. */
if (selection instanceof StructuredSelection) {
/* Get an iterator to iterate over the selection. */
Iterator<?> selectionIt;
selectionIt = ((StructuredSelection) selection).iterator();
/* Clear the currently selected model results. */
this.currentlySelectedRows.clear();
while (selectionIt.hasNext()) {
Object anObject;
anObject = selectionIt.next();
/* Check if the selected entry is an array. */
if (anObject.getClass().isArray()) {
Object[] aRow;
aRow = (Object[]) anObject;
this.currentlySelectedRows.add(aRow);
}
// no else.
}
// end while
}
// no else (no structured selection, could not happen).
}
// no else (nothing has to be updated).
}
/**
* <p>
* Passing the focus request to the viewer's control.
* </p>
*/
public void setFocus() {
this.myTableViewer.getControl().setFocus();
}
/**
* <p>
* Adds a given {@link IInterpretationResult} to the results of this
* {@link InterpreterView}.
* </p>
*
* @param interpretationResult
* The {@link IInterpretationResult} that shall be added.
*/
public void addInterpretationResult(
IInterpretationResult interpretationResult) {
this.myResults.addResult(interpretationResult);
}
/**
* <p>
* Clears the {@link IInterpretationResult} of this {@link InterpreterView}.
* </p>
*/
public void clearResults() {
this.myResults.clear();
this.refreshView();
}
/**
* <p>
* Clears the {@link IInterpretationResult} of this {@link InterpreterView}
* for the currently selected {@link IModelInstanceElement}s and
* {@link Constraint}s.
* </p>
*/
public void clearResultsForSelection() {
this.myResults.removeResults(new ArrayList<IModelInstanceElement>(
this.currentlySelectedModelInstanceElements),
new ArrayList<Constraint>(this.currentlySelectedConstraints));
this.myResults.removeResults(this.currentlySelectedRows);
}
/**
* <p>
* Returns the currently selected {@link Constraint}s that shall be
* interpreted.
* </p>
*
* @return The currently selected {@link Constraint}s that shall be
* interpreted.
*/
public Set<Constraint> getCurrentlySelectedConstraints() {
return this.currentlySelectedConstraints;
}
/**
* <p>
* Returns the currently selected {@link IModelInstance}.
* </p>
*
* @return The currently selected {@link IModelInstance}.
*/
public IModelInstance getCurrentlySelectedModelInstance() {
return this.currentlySelectedModelInstance;
}
/**
* <p>
* Returns the currently selected {@link IModelInstanceElement}s that shall
* be interpreted.
* </p>
*
* @return The currently selected {@link IModelInstanceElement}s that shall
* be interpreted.
*/
public Set<IModelInstanceElement> getCurrentlySelectedModelInstanceElements() {
return this.currentlySelectedModelInstanceElements;
}
/**
* <p>
* Returns the {@link IOclInterpreter} for a given {@link IModelInstance}.
* </p>
*
* @param modelInstance
* The {@link IModelInstance} for that the
* {@link IOclInterpreter} shall be returned.
* @return The {@link IOclInterpreter} for a given {@link IModelInstance}
*/
public IOclInterpreter getInterpreterForInstance(
IModelInstance modelInstance) {
IOclInterpreter result;
result = this.myCachedInterpreters.get(modelInstance);
if (result == null) {
result = OclInterpreterPlugin.createInterpreter(modelInstance);
this.myCachedInterpreters.put(modelInstance, result);
}
// no else.
return result;
}
/**
* <p>
* Returns the {@link TableViewer} used to present the results of the
* interpretation.
* </p>
*
* @return The {@link TableViewer} used to present the results of the
* interpretation.
*/
public TableViewer getTableViewer() {
return this.myTableViewer;
}
/**
* <p>
* Returs the {@link InterpretationResultCache} of this
* {@link InterpreterView}.
* </p>
*
* @return The {@link InterpretationResultCache} of this
* {@link InterpreterView}.
*/
public InterpretationResultCache getResults() {
return this.myResults;
}
/**
* <p>
* Refreshes this {@link InterpreterView}.
* </p>
*/
public void refreshView() {
/* Execute in a GUI thread to avoid IllegalThreadExceptions. */
ModelBusUIPlugin.getDefault().getWorkbench().getDisplay()
.asyncExec(new Runnable() {
public void run() {
myTableViewer.refresh();
for (TableColumn column : myTableViewer.getTable()
.getColumns()) {
column.pack();
}
}
});
}
/**
* <p>
* Opens a MessageDialog and shows a given message.
* </p>
*
* @param message
* The message which shall be shown.
*/
public void showMessage(String message) {
MessageDialog.openInformation(this.myTableViewer.getControl()
.getShell(),
OclInterpreterUIMessages.InterpreterView_InterpreterResults,
message);
}
/**
* <p>
* Adds a {@link Constraint} to the current {@link Constraint} selection.
* </p>
*
* @param aConstraint
* The {@link Constraint} which shall be added.
*/
private void addConstraintSelection(Constraint aConstraint) {
this.currentlySelectedConstraints.add(aConstraint);
}
/**
* <p>
* Adds a {@link IModelInstanceElement} to the current
* {@link IModelInstanceElement} selection.
* </p>
*
* @param modelObject
* The {@link IModelInstanceElement}s that shall be added.
*/
private void addModelObjectSelection(IModelInstanceElement modelObject) {
this.currentlySelectedModelInstanceElements.add(modelObject);
}
/**
* <p>
* Adds all {@link IModelInstanceElement} of a given {@link Type} to the
* actions that need {@link IModelInstanceElement} selection.
* </p>
*
* @param type
* The {@link Type} whose {@link IModelInstanceElement}s shall be
* added.
*/
private void addModelObjectSelection(Type type) {
if (this.currentlySelectedModelInstance != null) {
this.currentlySelectedModelInstanceElements
.addAll(this.currentlySelectedModelInstance
.getAllInstances(type));
}
// no else.
}
/**
* <p>
* Clears the {@link Constraint} selection for all actions which need
* {@link Constraint} selection.
* </p>
*/
private void clearConstraintSelection() {
this.currentlySelectedConstraints.clear();
}
/**
* <p>
* Clears the {@link IModelInstanceElement} selection for all actions which
* need {@link IModelInstanceElement} selection.
* </p>
*/
private void clearModelObjectSelection() {
this.currentlySelectedModelInstanceElements.clear();
}
@Override
public void interpretationFinished(InterpreterRegistryEvent event) {
addInterpretationResult(event.getInterpreationResult());
refreshView();
}
}