blob: 8afb7acf975df966eb15a4149bacb9ce0de13f3c [file] [log] [blame]
//------------------------------------------------------------------------------
// Copyright (c) 2005, 2008 IBM Corporation and others.
// 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:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.authoring.ui.dialogs;
import java.lang.reflect.InvocationTargetException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryContentProvider;
import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
import org.eclipse.epf.authoring.ui.AuthoringUIPlugin;
import org.eclipse.epf.authoring.ui.AuthoringUIResources;
import org.eclipse.epf.authoring.ui.actions.LibraryViewSimpleAction;
import org.eclipse.epf.authoring.ui.actions.UnassignAction;
import org.eclipse.epf.authoring.ui.forms.CustomCategoryAssignPage;
import org.eclipse.epf.common.ui.util.MsgDialog;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.edit.TngAdapterFactory;
import org.eclipse.epf.library.edit.ui.UserInteractionHelper;
import org.eclipse.epf.library.edit.util.IRunnableWithProgress;
import org.eclipse.epf.library.edit.util.ModelStructure;
import org.eclipse.epf.library.edit.util.TngUtil;
import org.eclipse.epf.library.edit.validation.UniqueNamePNameHandler;
import org.eclipse.epf.library.services.LibraryModificationHelper;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.library.util.ResourceScanner;
import org.eclipse.epf.uma.ContentPackage;
import org.eclipse.epf.uma.CustomCategory;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.epf.uma.MethodPlugin;
import org.eclipse.epf.uma.UmaFactory;
import org.eclipse.epf.uma.UmaPackage;
import org.eclipse.epf.uma.util.UmaUtil;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.wizard.ProgressMonitorPart;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
/**
* Dialog for assiging MethodElement within MethodLibrary.
*
* @author Weiping Lu
* @since 1.5
*/
public class AssignDialog extends Dialog implements ISelectionChangedListener {
ArrayList usedCategories = new ArrayList();
private TreeViewer treeViewer;
private ArrayList elements;
private Object destination;
private boolean assigning = false;
private ProgressMonitorPart progressMonitorPart;
private Cursor waitCursor;
private boolean lockedUI = false;
public static AssignDialog newAssignDialog(Shell parentShell, Collection elements) {
return new AssignDialog(parentShell, elements);
}
public static AssignDialog newReassignDialog(Shell parentShell,
Collection elements, MethodElement parentElement) {
return new ReassignDialog(parentShell, elements, parentElement);
}
public static AssignDialog newDeepCopyDialog(Shell parentShell, Collection elements) {
return new CustomCategoryDeepCopyDialog(parentShell, elements);
}
protected AssignDialog(Shell parentShell, Collection elementsToAssign) {
super(parentShell);
elements = new ArrayList();
elements.addAll(elementsToAssign);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
*/
protected Control createDialogArea(Composite parent) {
Composite composite = (Composite) super.createDialogArea(parent);
GridLayout layout = (GridLayout) composite.getLayout();
layout.marginWidth = 10;
layout.marginHeight = 10;
Label label = new Label(composite, SWT.NONE);
label.setText(AuthoringUIResources.MoveDialog_destination_text);
GridData layoutData = new GridData(SWT.BEGINNING);
label.setLayoutData(layoutData);
treeViewer = new TreeViewer(composite, SWT.SINGLE | SWT.H_SCROLL
| SWT.V_SCROLL | SWT.BORDER);
AdapterFactory adapterFactory = TngAdapterFactory.INSTANCE
.getNavigatorView_ComposedAdapterFactory();
treeViewer.setLabelProvider(new AdapterFactoryLabelProvider(
adapterFactory));
treeViewer.setContentProvider(new AdapterFactoryContentProvider(
adapterFactory));
treeViewer.addSelectionChangedListener(this);
// treeViewer.addDoubleClickListener(this);
GridData spec = new GridData(GridData.FILL_BOTH);
{
spec.widthHint = 300;
spec.heightHint = 300;
treeViewer.getControl().setLayoutData(spec);
}
treeViewer.setInput(LibraryService.getInstance().getCurrentMethodLibrary());
GridLayout pmlayout = new GridLayout();
pmlayout.numColumns = 1;
progressMonitorPart = createProgressMonitorPart(composite, pmlayout);
progressMonitorPart
.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
progressMonitorPart.setVisible(false);
waitCursor = parent.getShell().getDisplay().getSystemCursor(
SWT.CURSOR_WAIT);
return composite;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
*/
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText(AuthoringUIResources.AssignDialog_assign_text);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.viewers.ISelectionChangedListener#selectionChanged(org.eclipse.jface.viewers.SelectionChangedEvent)
*/
public void selectionChanged(SelectionChangedEvent event) {
destination = TngUtil.unwrap(((IStructuredSelection) event
.getSelection()).getFirstElement());
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.dialogs.Dialog#okPressed()
*/
protected void okPressed() {
if (doAssign()) {
super.okPressed();
}
}
private boolean isValidDestination() {
if (! (destination instanceof CustomCategory) ) {
return false;
}
if (elements == null || elements.isEmpty()) {
return false;
}
MethodPlugin targetPlugin = LibraryUtil.getMethodPlugin((CustomCategory) destination);
if (targetPlugin == null) {
return false;
}
if (elements.get(0) instanceof MethodElement) {
MethodPlugin sourcePlugin = LibraryUtil.getMethodPlugin((MethodElement) elements.get(0));
if (sourcePlugin == targetPlugin) {
return true;
}
if (targetPlugin.getBases().contains(sourcePlugin)) {
return true;
}
}
return false;
}
/**
* @return
*/
private boolean doAssign() {
//To do:
//(1) Implement circular dependency check for isValidDestination (nice to have the check
// at this point, although the circulat check would be done during "run" action too
//(2) Change "move" to "assign" strings
if (destination == null) {
String title = AuthoringUIResources.errorDialog_title;
String problem = AuthoringUIResources.MoveDialog_nomove_destination_problem_msg;
String msg = AuthoringUIResources.MoveDialog_selectdestination_text;
MsgDialog dialog = AuthoringUIPlugin.getDefault().getMsgDialog();
dialog.displayError(title, problem, msg);
return false;
}
if (!isValidDestination()) {
String title = AuthoringUIResources.errorDialog_title;
String problem = AuthoringUIResources.MoveDialog_invalid_move_destination_problem_msg;
String msg = AuthoringUIResources.MoveDialog_validdestination_text;
MsgDialog dialog = AuthoringUIPlugin.getDefault().getMsgDialog();
dialog.displayError(title, problem, msg);
return false;
} else {
IStatus status = UserInteractionHelper.checkModify(
(EObject) destination, getShell());
if (!status.isOK()) {
String title = AuthoringUIResources.errorDialog_title;
String msg = AuthoringUIResources.MoveDialog_cannotModifyDestination;
MsgDialog dialog = AuthoringUIPlugin.getDefault()
.getMsgDialog();
dialog.displayError(title, msg, status);
return false;
}
}
assigning = true;
IRunnableWithProgress runnable = new IRunnableWithProgress() {
public void run(IProgressMonitor monitor)
throws InvocationTargetException, InterruptedException {
monitor.subTask(AuthoringUIResources.assignAction_text);
try {
Collection<Resource> resouresToSave = doWorkBeforeSave();
LibraryViewSimpleAction.save(resouresToSave);
} finally {
assigning = false;
}
}
};
final Shell shell = getShell();
shell.setCursor(waitCursor);
getButton(IDialogConstants.OK_ID).setEnabled(false);
getButton(IDialogConstants.CANCEL_ID).setEnabled(false);
treeViewer.getControl().setEnabled(false);
progressMonitorPart.setVisible(true);
IStatus stat = null;
try {
stat = UserInteractionHelper.getUIHelper().runInModalContext(runnable, true, progressMonitorPart, shell);
} catch (Exception e) {
AuthoringUIPlugin.getDefault().getLogger().logError(e);
return true;
} finally {
progressMonitorPart.done();
}
if(stat != null && !stat.isOK()) {
String title = AuthoringUIResources.errorDialog_title;
String msg = AuthoringUIResources.dialogs_AssignDialog_errorMessage;
MsgDialog dialog = AuthoringUIPlugin.getDefault()
.getMsgDialog();
dialog.displayError(title, msg, stat);
}
return true;
}
protected Collection<Resource> doWorkBeforeSave() {
final LibraryModificationHelper helper = new LibraryModificationHelper();
final CustomCategory category = (CustomCategory) destination;
final Collection<Resource> resouresToSave = new HashSet<Resource>();
getShell().getDisplay().syncExec(new Runnable() {
public void run() {
CustomCategoryAssignPage.addItemsToModel1(elements, category,
usedCategories, helper.getActionManager(),
CustomCategoryAssignPage.getAncestors(category));
resouresToSave.add(category.eResource());
}
});
return resouresToSave;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.dialogs.Dialog#close()
*/
public boolean close() {
if (assigning)
return false;
return super.close();
}
protected ProgressMonitorPart createProgressMonitorPart(
Composite composite, GridLayout pmlayout) {
return new ProgressMonitorPart(composite, pmlayout, SWT.DEFAULT) {
String currentTask = null;
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.ProgressMonitorPart#setBlocked(org.eclipse.core.runtime.IStatus)
*/
public void setBlocked(IStatus reason) {
super.setBlocked(reason);
if (!lockedUI)// Do not show blocked if we are locking the UI
getBlockedHandler().showBlocked(getShell(), this, reason,
currentTask);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.ProgressMonitorPart#clearBlocked()
*/
public void clearBlocked() {
super.clearBlocked();
if (!lockedUI)// Do not vlear if we never set it
getBlockedHandler().clearBlocked();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.ProgressMonitorPart#beginTask(java.lang.String,
* int)
*/
public void beginTask(String name, int totalWork) {
super.beginTask(name, totalWork);
currentTask = name;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.ProgressMonitorPart#setTaskName(java.lang.String)
*/
public void setTaskName(String name) {
super.setTaskName(name);
currentTask = name;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.jface.wizard.ProgressMonitorPart#subTask(java.lang.String)
*/
public void subTask(String name) {
super.subTask(name);
// If we haven't got anything yet use this value for more
// context
if (currentTask == null)
currentTask = name;
}
};
}
protected ArrayList getElements() {
return elements;
}
protected Object getDestination() {
return destination;
}
private static class ReassignDialog extends AssignDialog {
private CustomCategory parentElement;
protected ReassignDialog(Shell parentShell,
Collection elements, MethodElement parentElement) {
super(parentShell, elements);
this.parentElement = (CustomCategory) parentElement;
}
protected Collection<Resource> doWorkBeforeSave() {
Collection<Resource> resouresToSave = super.doWorkBeforeSave();
resouresToSave.add(parentElement.eResource());
UnassignAction.unassign(getShell(), getElements().get(0), parentElement, new ArrayList());
return resouresToSave;
}
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText(AuthoringUIResources.AssignDialog_reassign_text);
}
}
private static class CustomCategoryDeepCopyDialog extends AssignDialog {
ContentPackage customCategoryPkg;
private UniqueNamePNameHandler nameHandler;
private ResourceScanner scanner;
protected CustomCategoryDeepCopyDialog(Shell parentShell,
Collection elements) {
super(parentShell, elements);
}
protected Collection<Resource> doWorkBeforeSave() {
if (getElements() == null
|| !(getElements().get(0) instanceof CustomCategory)
|| !(getDestination() instanceof CustomCategory)) {
return null;
}
CustomCategory source = (CustomCategory) getElements().get(0);
CustomCategory targetParent = (CustomCategory) getDestination();
initDeepCopy(source, targetParent);
CustomCategory copy = (CustomCategory) deepCopy(source);
//ITextReferenceReplacer txtRefReplacer = ExtensionManager.getTextReferenceReplacer();
customCategoryPkg.getContentElements().add(copy);
targetParent.getCategorizedElements().add(copy);
Collection<Resource> resouresToSave = new ArrayList();
resouresToSave.add(targetParent.eResource());
if (scanner != null) {
scanner.copyFiles();
}
return resouresToSave;
}
private EObject deepCopy(EObject source) {
EObject copy = UmaFactory.eINSTANCE.create(source.eClass());
handleNames(source, copy);
List features = source.eClass().getEAllStructuralFeatures();
for (int i = 0; i < features.size(); i++) {
EStructuralFeature feature = (EStructuralFeature) features.get(i);
//System.out.println("LD> feature: " + feature.getName());
copyFeatureValue(source, copy, feature);
}
return copy;
}
private void handleNames(EObject source, EObject copy) {
if (copy instanceof CustomCategory) {
Object name = source.eGet(UmaPackage.eINSTANCE.getNamedElement_Name());
Object pname = source.eGet(UmaPackage.eINSTANCE.getMethodElement_PresentationName());
copy.eSet(UmaPackage.eINSTANCE.getNamedElement_Name(), name);
copy.eSet(UmaPackage.eINSTANCE.getMethodElement_PresentationName(), pname);
nameHandler.ensureUnique((CustomCategory) copy);
}
}
private void copyFeatureValue(EObject sourceObj, EObject copiedObj, EStructuralFeature feature) {
if (feature instanceof EAttribute) {
copyAttributeFeatureValue(sourceObj, copiedObj, (EAttribute) feature);
} else if (feature instanceof EReference) {
copyReferenceFeatureValue(sourceObj, copiedObj, (EReference) feature);
}
}
private void copyAttributeFeatureValue(EObject sourceObj,
EObject copiedObj, EAttribute feature) {
Object sourceValue = sourceObj.eGet(feature);
if (sourceValue == null) {
return;
}
Object copiedValue = sourceValue;
if (sourceObj instanceof CustomCategory) {
if (feature == UmaPackage.eINSTANCE.getMethodElement_Guid()) {
copiedValue = EcoreUtil.generateUUID();
} else if (feature == UmaPackage.eINSTANCE.getNamedElement_Name()) {
return;
} else if (feature == UmaPackage.eINSTANCE.getMethodElement_PresentationName()) {
return;
}
}
if (scanner != null) {
if (sourceValue instanceof URI) {
URI uri = (URI) sourceValue;
String urlStr = scanner.registerFileCopy(uri.toString());
try {
copiedValue = new URI(urlStr);
} catch (Exception e) {
copiedValue = sourceValue;
}
} else if (sourceValue instanceof String) {
if (sourceObj instanceof MethodElement
&& copiedObj instanceof MethodElement) {
copiedValue = scanner
.scan((MethodElement) sourceObj,
(MethodElement) copiedObj,
(String) sourceValue, feature);
}
}
}
copiedObj.eSet(feature, copiedValue);
}
private void copyReferenceFeatureValue(EObject sourceObj, EObject copiedObj, EReference feature) {
Object sourceValue = sourceObj.eGet(feature);
if (sourceValue == null) {
return;
}
Object copiedValue = sourceValue;
if (feature.isContainment()) {
if (feature.isMany()) {
List<EObject> sourceList = (List<EObject>) sourceValue;
List<EObject> copiedList = (List<EObject>) copiedObj
.eGet(feature);
for (EObject sobj : sourceList) {
EObject cobj = deepCopy(sobj);
copiedList.add(cobj);
}
return;
}
copiedValue = deepCopy((EObject) sourceValue);
} else if (feature.isMany()) {
List sourceList = (List) sourceValue;
List copiedList = (List) copiedObj.eGet(feature);
for (Object sobj : sourceList) {
Object cobj = sobj;
if (sobj instanceof CustomCategory) {
cobj = (CustomCategory) deepCopy((CustomCategory) sobj);
CustomCategory ccobj = (CustomCategory) cobj;
customCategoryPkg.getContentElements().add(ccobj);
}
copiedList.add(cobj);
}
return;
}
copiedObj.eSet(feature, copiedValue);
}
protected void configureShell(Shell newShell) {
super.configureShell(newShell);
newShell.setText(AuthoringUIResources.deepCopy_text);
}
private void initDeepCopy(CustomCategory source, CustomCategory targetParent) {
MethodPlugin srcPlugin = UmaUtil.getMethodPlugin(source);
MethodPlugin tgtPlugin = UmaUtil.getMethodPlugin(targetParent);
customCategoryPkg = UmaUtil.findContentPackage(tgtPlugin, ModelStructure.DEFAULT.customCategoryPath);
nameHandler = new UniqueNamePNameHandler(customCategoryPkg.getContentElements());
if (srcPlugin != tgtPlugin) {
scanner = new ResourceScanner(srcPlugin, tgtPlugin);
}
}
}
}