/**
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Copyright (C) 2007 Matthias Braeuer (braeuer.matthias@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 *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* $Id$
*/
package org.dresdenocl.modelbus.ui.internal.wizards;
import java.io.File;
import java.lang.reflect.Method;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
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.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.dresdenocl.model.IModel;
import org.dresdenocl.model.metamodel.IMetamodel;
import org.dresdenocl.modelbus.ModelBusPlugin;
import org.dresdenocl.modelbus.ui.internal.ModelBusUIMessages;
import org.dresdenocl.modelbus.ui.internal.wizards.util.AbstractModelBusPage;
import org.dresdenocl.modelbus.ui.internal.wizards.util.BrowseFileListener;
import org.dresdenocl.modelbus.ui.internal.wizards.util.BrowseWorkspaceListener;
import org.dresdenocl.modelbus.ui.internal.wizards.util.FileBoxListener;
import org.dresdenocl.modelbus.ui.internal.wizards.util.MetaModelLabelProvider;
import org.dresdenocl.modelbus.ui.internal.wizards.util.ModelViewerListener;
import org.dresdenocl.modelbus.util.ModelLoaderUtility;
/**
* <p>
* The {@link LoadModelPage} is used by the {@link LoadModelWizard} to select a
* model file and a meta model for which the model shall be imported.
* </p>
*
* @author Matthias Braeuer
*/
public class LoadModelPage extends AbstractModelBusPage {
/**
* The selection in the workspace, cached to automatically suggest the
* selected file.
*/
private IStructuredSelection selection;
/** The text field that contains the project file name. */
private Text modelFileTextBox;
/** The viewer displaying the registered meta models. */
private StructuredViewer metamodelViewer;
/**
* <p>
* Creates a new {@link LoadModelPage}.
* </p>
*
* @param selection
* A parent selection which can be used by the page to set a
* previously selected file as model file.
*/
public LoadModelPage(IStructuredSelection selection) {
super("LoadModelPage");
this.selection = selection;
this.setTitle(ModelBusUIMessages.LoadModelPage_Title);
this.setDescription(ModelBusUIMessages.LoadModelPage_Description);
}
/*
* (non-Javadoc)
* @see
* org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets
* .Composite)
*/
public void createControl(Composite parent) {
Composite panel;
GridLayout layout;
/* Create panel. */
panel = new Composite(parent, SWT.NONE);
/* Set panel attributes. */
layout = new GridLayout(1, true);
layout.verticalSpacing = 20;
panel.setLayout(layout);
panel.setFont(parent.getFont());
/* Create UI elements. */
this.createModelFileGroup(panel);
this.createMetamodelSelectionGroup(panel);
/* Set the initial selection. */
this.initializeFromSelection();
this.updatePageComplete();
/* Set font. */
Dialog.applyDialogFont(parent);
/* Connect the wizard page with the wizard. */
this.setControl(panel);
}
/*
* (non-Javadoc)
* @see org.dresdenocl.modelbus.ui.internal.wizards.AbstractModelBusPage
* #setFileTextBoxText(java.lang.String)
*/
public void setFileTextBoxText(String text) {
this.modelFileTextBox.setText(text);
}
/*
* (non-Javadoc)
* @see org.dresdenocl.modelbus.ui.internal.wizards.AbstractModelBusPage
* #updatePageComplete()
*/
public void updatePageComplete() {
String modelFileName;
IPath modelFilePath;
File modelFile;
boolean complete;
/* Reset the messages. */
this.setErrorMessage(null);
this.setMessage(null);
/* By default the page is complete. */
complete = true;
/* Read out model file name. */
modelFileName = this.getModelFileName();
/* Check if model file name is empty. */
if (modelFileName.length() == 0) {
this.setMessage(ModelBusUIMessages.LoadModelPage_MessagePleaseChooseModel);
complete = false;
}
else {
/* Substitute variables in string. */
modelFileName = this.decodePath(modelFileName);
if (modelFileName == null) {
this.setErrorMessage(ModelBusUIMessages.LoadModelPage_ErrorMsgInvalidVariables);
complete = false;
}
else {
/* Create a path for the project file. */
modelFilePath = new Path(modelFileName);
/* Check if project file exists. */
modelFile = modelFilePath.toFile();
if (modelFile == null || !modelFile.exists()) {
this.setErrorMessage(ModelBusUIMessages.LoadModelPage_ErrorMsgModelFileNotExisting);
complete = false;
}
// no else.
/* Automaticly select the correct metamodel */
selectMetaModelByModelFilePath(modelFilePath);
/* Check if the corresponding .class file exists */
if (complete
&& modelFilePath.getFileExtension().equalsIgnoreCase("java")
&& !new File(
ModelLoaderUtility.getCorrespondingClassFileName(modelFileName))
.exists()) {
this.setErrorMessage(ModelBusUIMessages.LoadModelPage_ErrorMsgCorrespondingClassFileNotExisting);
complete = false;
}
// no else
}
// end else.
}
// end else.
/* Check that a meta model has been selected. */
if (complete && !this.isMetamodelSelected()) {
this.setErrorMessage(ModelBusUIMessages.LoadModelPage_SelectMetamodelErrorMessage);
complete = false;
}
// no else.
setPageComplete(complete);
}
/**
* <p>
* Returns a {@link File} representing the currently selected model file.
* </p>
*
* @return The selected model {@link File} or <code>null</code>.
*/
public File getModelFile() {
File result;
String modelFileName;
IPath modelFilePath;
/** By default the model file is null. */
result = null;
/** Determine the selected model file name. */
modelFileName = decodePath(getModelFileName());
if (modelFileName != null) {
modelFilePath = new Path(modelFileName);
/* Get the path to the corresponding .class file if needed */
if (modelFilePath.getFileExtension().equalsIgnoreCase("java")) {
modelFilePath =
new Path(
ModelLoaderUtility.getCorrespondingClassFileName(modelFileName));
}
// no else.
result = modelFilePath.toFile();
}
// no else.
return result;
}
/**
* <p>
* Returns the selected {@link IMetamodel} or <code>null</code> if no meta
* model is selected.
* </p>
*
* @return An {@link IMetamodel} instance or <code>null</code>.
*/
public IMetamodel getSelectedMetamodel() {
IMetamodel result;
result =
(IMetamodel) ((IStructuredSelection) this.metamodelViewer
.getSelection()).getFirstElement();
return result;
}
/**
* <p>
* A helper method that creates the {@link IMetamodel} selection part.
* </p>
*
* @param parent
* The parent {@link Composite} of this part.
*/
private void createMetamodelSelectionGroup(Composite parent) {
Composite metamodelSelectionGroup;
Label explanationText;
GridLayout layout;
/* Create meta model selection group and specify properties. */
metamodelSelectionGroup = new Composite(parent, SWT.NONE);
metamodelSelectionGroup.setFont(parent.getFont());
metamodelSelectionGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL,
true, true));
layout = new GridLayout(1, false);
layout.verticalSpacing = 10;
metamodelSelectionGroup.setLayout(layout);
/* Create the explanation label. */
explanationText = new Label(metamodelSelectionGroup, SWT.WRAP);
explanationText
.setText(ModelBusUIMessages.LoadModelPage_SelectMetamodelLabel);
/* Create the list viewer to display the meta models. */
this.metamodelViewer =
new TableViewer(metamodelSelectionGroup, SWT.SINGLE | SWT.V_SCROLL
| SWT.BORDER);
this.metamodelViewer.setContentProvider(new ArrayContentProvider());
this.metamodelViewer.setLabelProvider(new MetaModelLabelProvider());
this.metamodelViewer.setInput(ModelBusPlugin.getMetamodelRegistry()
.getMetamodels());
this.metamodelViewer.getControl().setLayoutData(
new GridData(SWT.FILL, SWT.FILL, true, true));
this.metamodelViewer.addSelectionChangedListener(new ModelViewerListener(
this));
}
/**
* <p>
* A helper method that creates the SWT group that allows selecting the
* {@link IModel} file.
* </p>
*
* @param parent
* The {@link Composite} parent of this {@link Group}.
*/
private void createModelFileGroup(Composite parent) {
Composite modelFileGroupComposite;
Group modelFileGroup;
Label locationLabel, spacer;
Button fBrowseWorkspaceButton, fBrowseFileButton;
GridLayout layout;
/*
* Create a composite around the group so the margins are equal to the
* metamodel selection.
*/
modelFileGroupComposite = new Composite(parent, SWT.None);
modelFileGroupComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true,
false));
/* We need another GridLayout to properly set additional margins. */
layout = new GridLayout();
modelFileGroupComposite.setLayout(layout);
/* Create model file group and specify properties. */
modelFileGroup = new Group(modelFileGroupComposite, SWT.NONE);
modelFileGroup.setText(ModelBusUIMessages.LoadModelPage_ModelFileGroupText);
modelFileGroup.setLayoutData(new GridData(SWT.FILL, SWT.NONE, true, false));
layout = new GridLayout(4, false);
layout.horizontalSpacing = 10;
modelFileGroup.setLayout(layout);
modelFileGroup.setFont(parent.getFont());
/* Create the text label. */
locationLabel = new Label(modelFileGroup, SWT.None);
locationLabel.setText(ModelBusUIMessages.LoadModelPage_LocationLabelText);
/* Create the text box. */
modelFileTextBox = new Text(modelFileGroup, SWT.SINGLE | SWT.BORDER);
modelFileTextBox.setLayoutData(new GridData(SWT.FILL, SWT.NORMAL, true,
false, 3, 1));
/* Track modifications. */
modelFileTextBox.addModifyListener(new FileBoxListener(this));
/* The spacing label. */
spacer = new Label(modelFileGroup, SWT.NONE);
spacer.setLayoutData(new GridData(SWT.FILL, SWT.NORMAL, true, false, 2, 1));
/* Create buttons. */
fBrowseWorkspaceButton =
createButton(modelFileGroup,
ModelBusUIMessages.LoadModelPage_BrowseWorkspaceButtonText);
fBrowseFileButton =
createButton(modelFileGroup,
ModelBusUIMessages.LoadModelPage_BrowseFileSystemButtonText);
/* Add the listeners. */
fBrowseWorkspaceButton.addSelectionListener(new BrowseWorkspaceListener(
this));
fBrowseFileButton.addSelectionListener(new BrowseFileListener(this));
}
/**
* <p>
* A helper method to return the name of the {@link IModel} file.
* </p>
*
* @return The name of the {@link IModel} file.
*/
private String getModelFileName() {
return modelFileTextBox.getText().trim();
}
/**
* <p>
* A helper method to check whether a {@link IMetamodel} has been selected.
* </p>
*
* @return True if a {@link IMetamodel} has been selected.
*/
private boolean isMetamodelSelected() {
return !((IStructuredSelection) this.metamodelViewer.getSelection())
.isEmpty();
}
/**
* <p>
* A helper method which initializes the file selection area from the
* selection in the workspace.
* </p>
*/
private void initializeFromSelection() {
IMetamodel[] metaModels;
String fileTextBoxContent = null;
if (this.selection != null && this.selection.getFirstElement() != null) {
Object selectedObject = this.selection.getFirstElement();
/*
* Determine the CorrespondingResource to a CompilationUnit-Object (e.g.
* .java Files in the src directory) Reflection is used here to avoid
* introducing a dependency to the JDT-Framework, just in case that
* somebody uses DresdenOCL without Java
*/
if (selectedObject.getClass().getName()
.equals("org.eclipse.jdt.internal.core.CompilationUnit")) {
try {
Method method =
selectedObject.getClass().getMethod("getCorrespondingResource");
selectedObject = (IResource) method.invoke(selectedObject);
} catch (Exception e) {
/* If invocation fails, selection will be discarded */
selectedObject = null;
}
}
if (selectedObject instanceof IResource) {
IResource selectedResource;
selectedResource = (IResource) selectedObject;
if (selectedResource.getType() == IResource.FILE) {
fileTextBoxContent = selectedResource.getRawLocation().toString();
modelFileTextBox.setText(fileTextBoxContent);
}
// no else
}
// no else.
}
// no else.
/* By default select the first meta model. */
metaModels = ModelBusPlugin.getMetamodelRegistry().getMetamodels();
if (metaModels.length > 0) {
this.metamodelViewer.setSelection(new StructuredSelection(metaModels[0]));
}
// no else.
}
/**
* <p>
* Selects the metamodel in the metamodelviewer depending on the filetype
* given by the path parameter...
* </p>
*
* @param The
* {@link IPath} to the model file
*/
private void selectMetaModelByModelFilePath(IPath modelFilePath) {
if (modelFilePath == null) {
return;
}
IMetamodel mm =
ModelLoaderUtility.getMetamodelByExtension(modelFilePath
.getFileExtension());
StructuredSelection selection = new StructuredSelection(mm);
/*
* Avoid endless loop due to the eventhandler is called for every
* setSelection()
*/
if (!this.metamodelViewer.getSelection().equals(selection)) {
this.metamodelViewer.setSelection(selection);
}
}
}