blob: c5de8ad6bfbd03462da4ba0b5dd689ca6c0d33a2 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007-2019 Cisco Systems, Inc.
* 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:
* E. Dillon (Cisco Systems, Inc.) - reformat for Code Open-Sourcing
*******************************************************************************/
package org.eclipse.tigerstripe.workbench.ui.internal.editors.descriptor.dependencies;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.core.ElementChangedEvent;
import org.eclipse.jdt.core.IElementChangedListener;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaElementDelta;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.Window;
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.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.tigerstripe.workbench.TigerstripeException;
import org.eclipse.tigerstripe.workbench.internal.api.impl.AbstractTigerstripeProjectHandle;
import org.eclipse.tigerstripe.workbench.internal.api.impl.TigerstripeProjectHandle;
import org.eclipse.tigerstripe.workbench.internal.core.module.InstalledModule;
import org.eclipse.tigerstripe.workbench.internal.core.project.Dependency;
import org.eclipse.tigerstripe.workbench.internal.core.project.InternalTigerstripeProject;
import org.eclipse.tigerstripe.workbench.internal.core.project.ModelReference;
import org.eclipse.tigerstripe.workbench.project.IDependency;
import org.eclipse.tigerstripe.workbench.project.IModelReference;
import org.eclipse.tigerstripe.workbench.project.ITigerstripeModelProject;
import org.eclipse.tigerstripe.workbench.project.ITigerstripeModelProjectInternal;
import org.eclipse.tigerstripe.workbench.ui.EclipsePlugin;
import org.eclipse.tigerstripe.workbench.ui.components.md.MasterDetails;
import org.eclipse.tigerstripe.workbench.ui.components.md.MasterDetailsBuilder;
import org.eclipse.tigerstripe.workbench.ui.internal.dialogs.CustomTigerstripeDependenciesManager;
import org.eclipse.tigerstripe.workbench.ui.internal.dialogs.IProjectSelectionDialog;
import org.eclipse.tigerstripe.workbench.ui.internal.dialogs.TigerstripeProjectSelectionDialog;
import org.eclipse.tigerstripe.workbench.ui.internal.editors.TigerstripeFormPage;
import org.eclipse.tigerstripe.workbench.ui.internal.editors.descriptor.DescriptorEditor;
import org.eclipse.tigerstripe.workbench.ui.internal.editors.descriptor.TigerstripeDescriptorSectionPart;
import org.eclipse.tigerstripe.workbench.ui.internal.utils.TigerstripeLayoutFactory;
import org.eclipse.ui.forms.IManagedForm;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.ui.forms.widgets.FormToolkit;
/**
* Section used to define Tigerstripe dependencies. Look under tigerstripe.xml >
* Dependencies
*
* @author nmehrega
*/
public class ReferencedProjectsSection extends TigerstripeDescriptorSectionPart {
private CheckboxTableViewer viewer;
private Button editButton;
private Button removeButton;
private Button selectAllButton;
private Button deselectAllButton;
private MasterDetails masterDetails;
private ClasspathChangesListener classpathListener;
private Button modifyRuntimeDependencies;
private static final String DEP_CHECKBOX_LABEL = "Modify dependencies at generation time (advanced)";
private static final String ADVANCED_PROPERTY_MODIFY_DEP_AT_RUNTIME = "modifyDependenciesAtGenerationTime";
private class ClasspathChangesListener implements IElementChangedListener {
public void elementChanged(ElementChangedEvent event) {
IJavaElementDelta delta = event.getDelta();
IJavaElementDelta[] childs = delta.getAffectedChildren();
for (IJavaElementDelta child : childs) {
if (child.getElement().getElementType() == IJavaElement.JAVA_PROJECT) {
IJavaProject jProject = (IJavaProject) child.getElement();
if (isCurrentProject(jProject) && isClassPathChanged(child)) {
resolveReferencedModels();
refreshReferences();
}
}
}
}
private boolean isCurrentProject(IJavaProject jProject) {
IJavaProject jTsProject = getTSProject().getAdapter(IJavaProject.class);
return jTsProject != null && jTsProject.equals(jProject);
}
private boolean isClassPathChanged(IJavaElementDelta delta) {
return (delta.getFlags() & IJavaElementDelta.F_CLASSPATH_CHANGED) != 0
|| (delta.getFlags() & IJavaElementDelta.F_RESOLVED_CLASSPATH_CHANGED) != 0;
}
private void resolveReferencedModels() {
try {
IModelReference[] references = getTSProject().getModelReferences();
for (IModelReference reference : references) {
reference.getResolvedModel();
}
} catch (TigerstripeException e) {
EclipsePlugin.log(e);
}
}
private void refreshReferences() {
Control control = viewer.getControl();
if (!control.isDisposed()) {
control.getDisplay().asyncExec(ReferencedProjectsSection.this::refresh);
}
}
}
static class ReferencedProjectsContentProvider implements IStructuredContentProvider {
public Object[] getElements(Object inputElement) {
if (inputElement instanceof ITigerstripeModelProject) {
ITigerstripeModelProject project = (ITigerstripeModelProject) inputElement;
try {
IModelReference[] modelReferences = project.getModelReferences();
IDependency[] dependencies = project.getDependencies();
Object[] elements = new Object[modelReferences.length + dependencies.length];
System.arraycopy(modelReferences, 0, elements, 0, modelReferences.length);
System.arraycopy(dependencies, 0, elements, modelReferences.length, dependencies.length);
return elements;
} catch (TigerstripeException e) {
return new Object[0];
}
}
return new Object[0];
}
public void dispose() {
// N/A
}
public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
// N/A
}
}
static class ReferencedProjectsLabelProvider extends LabelProvider implements ITableLabelProvider {
public String getColumnText(Object obj, int index) {
if (obj instanceof ModelReference) {
ModelReference ref = (ModelReference) obj;
String modelId = ref.getToModelId();
String projectName = null;
String version = null;
if (ref.isResolved()) {
ITigerstripeModelProject project = ref.getResolvedModel();
projectName = project.getName();
try {
version = project.getProjectDetails().getVersion();
} catch (Exception e) {
}
}
StringBuilder buffer = new StringBuilder();
if (modelId != null && modelId.length() > 0) {
buffer.append(modelId);
} else {
buffer.append(projectName);
}
if (version != null && version.length() > 0) {
buffer.append(" (");
buffer.append(version);
buffer.append(")");
}
return buffer.toString();
} else if (obj instanceof IDependency) {
return ((IDependency) obj).getPath();
} else {
return "Unknown";
}
}
public Image getColumnImage(Object obj, int index) {
return getImage(obj);
}
@Override
public String getText(Object obj) {
return getColumnText(obj, 0);
}
@Override
public Image getImage(Object obj) {
return IMAGE_PROVIDER.getImage(obj);
}
}
public ReferencedProjectsSection(TigerstripeFormPage page, Composite parent, FormToolkit toolkit) {
super(page, parent, toolkit, ExpandableComposite.TITLE_BAR);
setTitle("Dependencies");
}
@Override
public void initialize(IManagedForm form) {
super.initialize(form);
createContent();
initializeDependencyEnablement();
classpathListener = new ClasspathChangesListener();
JavaCore.addElementChangedListener(classpathListener, ElementChangedEvent.POST_CHANGE);
}
private void initializeDependencyEnablement() {
InternalTigerstripeProject tsProject = getActualTSProject();
String enableModificationOfDepAtRuntime = null;
if (tsProject != null)
enableModificationOfDepAtRuntime = tsProject.getAdvancedProperty(ADVANCED_PROPERTY_MODIFY_DEP_AT_RUNTIME);
if (enableModificationOfDepAtRuntime != null && enableModificationOfDepAtRuntime.equalsIgnoreCase("true")) {
modifyRuntimeDependencies.setSelection(true);
int numOfDependencies = viewer.getTable().getItemCount();
for (int i = 0; i < numOfDependencies; i++) {
Object element = viewer.getElementAt(i);
if (element instanceof ModelReference) {
ModelReference reference = (ModelReference) element;
viewer.setChecked(reference, reference.isEnabled());
} else if (element instanceof IDependency) {
IDependency dependency = (IDependency) element;
viewer.setChecked(dependency, dependency.isEnabled());
}
}
selectAllButton.setEnabled(true);
deselectAllButton.setEnabled(true);
} else {
// Dependency modification at runtime is off
modifyRuntimeDependencies.setSelection(false);
selectAllButton.setEnabled(false);
deselectAllButton.setEnabled(false);
viewer.setAllChecked(true);
}
}
// TODO - Why do we need access to the internal project? Can we abstract it
// behind the interface?
private InternalTigerstripeProject getActualTSProject() {
Object input = viewer.getInput();
if (input instanceof TigerstripeProjectHandle) {
try {
return (InternalTigerstripeProject) ((TigerstripeProjectHandle) input).getTSProject();
} catch (TigerstripeException e) {
EclipsePlugin.logErrorMessage("Problem occured while getting Tigerstripe Project: "
+ StringUtils.defaultString(e.getMessage()), e);
}
}
return null;
}
@Override
public void dispose() {
if (classpathListener != null) {
JavaCore.removeElementChangedListener(classpathListener);
EclipsePlugin.getTigerStripeDependenciesManager().fireDisposed(getTSProject());
}
super.dispose();
}
@Override
protected void createContent() {
GridDataFactory.fillDefaults().grab(true, true).applyTo(getSection());
GridLayoutFactory.fillDefaults().applyTo(getSection());
GridLayoutFactory.fillDefaults().applyTo(getBody());
getSection().setClient(getBody());
Composite parent = getToolkit().createComposite(getBody());
GridDataFactory.fillDefaults().grab(true, true).applyTo(parent);
GridLayoutFactory.fillDefaults().numColumns(2).equalWidth(true).applyTo(parent);
Composite masterContainer = getToolkit().createComposite(parent);
Composite detailsContainer = getToolkit().createComposite(parent, SWT.NONE);
GridLayoutFactory.fillDefaults().margins(1, 1).numColumns(2).applyTo(masterContainer);
GridLayoutFactory.fillDefaults().applyTo(detailsContainer);
GridDataFactory.fillDefaults().grab(true, true).applyTo(masterContainer);
GridDataFactory.fillDefaults().grab(true, true).applyTo(detailsContainer);
createTable(masterContainer, getToolkit());
modifyRuntimeDependencies = new Button(parent, SWT.CHECK);
modifyRuntimeDependencies.setEnabled(true);
modifyRuntimeDependencies.setText(DEP_CHECKBOX_LABEL);
modifyRuntimeDependencies.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
InternalTigerstripeProject tsProject = getActualTSProject();
if (tsProject != null) {
tsProject.setAdvancedProperty(ADVANCED_PROPERTY_MODIFY_DEP_AT_RUNTIME,
modifyRuntimeDependencies.getSelection() ? "true" : "false");
}
if (modifyRuntimeDependencies.getSelection()) {
selectAllButton.setEnabled(true);
deselectAllButton.setEnabled(true);
if (tsProject != null) {
tsProject.setDirty();
}
} else {
enableAllDependencies(true);
selectAllButton.setEnabled(false);
deselectAllButton.setEnabled(false);
}
markPageModified();
}
});
getToolkit().paintBordersFor(masterContainer);
masterDetails = MasterDetailsBuilder.create()
.addDetail(ModelReference.class, getReferenceDetailsPage(getToolkit(), detailsContainer))
.addDetail(Dependency.class, new DependencyDetails(getToolkit(), detailsContainer)).build();
}
private ReferenceDetails getReferenceDetailsPage(FormToolkit toolkit, Composite container){
if (CustomTigerstripeDependenciesManager.hasCustomDetailsPage()) {
try {
return CustomTigerstripeDependenciesManager.makeReferenceDetailsPage(toolkit, container);
} catch (TigerstripeException t) {
EclipsePlugin.logErrorMessage("Failure createing Custom details Page",t);
}
}
return new ReferenceDetails(toolkit, container);
}
private void enableAllDependencies(boolean markAsDirty) {
boolean stateChanged = false;
// Walk through all dependencies and enable them.
int numOfDependencies = viewer.getTable().getItemCount();
for (int i = 0; i < numOfDependencies; i++) {
TableItem item = viewer.getTable().getItem(i);
if (!item.getChecked()) {
stateChanged = true;
item.setChecked(true);
Object element = viewer.getElementAt(i);
if (element instanceof ModelReference) {
ModelReference reference = (ModelReference) element;
reference.setEnabled(true);
} else if (element instanceof IDependency) {
IDependency dependency = (IDependency) element;
dependency.setEnabled(true);
}
}
}
InternalTigerstripeProject tsProject = getActualTSProject();
if (stateChanged && markAsDirty && tsProject != null) {
tsProject.setDirty();
markPageModified();
Object input = viewer.getInput();
if (input instanceof TigerstripeProjectHandle) {
((TigerstripeProjectHandle) input).markCacheAsDirty();
}
}
}
private void disableAllDependencies() {
boolean stateChanged = false;
// Walk through all dependencies and enable them.
int numOfDependencies = viewer.getTable().getItemCount();
for (int i = 0; i < numOfDependencies; i++) {
TableItem item = viewer.getTable().getItem(i);
if (item.getChecked()) {
stateChanged = true;
item.setChecked(false);
Object element = viewer.getElementAt(i);
if (element instanceof ModelReference) {
ModelReference reference = (ModelReference) element;
reference.setEnabled(false);
} else if (element instanceof IDependency) {
IDependency dependency = (IDependency) element;
dependency.setEnabled(false);
}
}
}
InternalTigerstripeProject tsProject = getActualTSProject();
if (stateChanged && tsProject != null) {
tsProject.setDirty();
markPageModified();
Object input = viewer.getInput();
if (input instanceof TigerstripeProjectHandle) {
((TigerstripeProjectHandle) input).markCacheAsDirty();
}
}
}
private void createTable(Composite parent, FormToolkit toolkit) {
Table t = toolkit.createTable(parent, SWT.NULL | SWT.MULTI | SWT.CHECK);
GridData gd = new GridData(GridData.FILL_BOTH);
gd.verticalSpan = 2;
t.setLayoutData(gd);
Composite buttonsClient = toolkit.createComposite(parent);
buttonsClient.setLayout(TigerstripeLayoutFactory.createButtonsGridLayout());
buttonsClient.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING));
// Add Dependency button
Button addButton = toolkit.createButton(buttonsClient, "Add...", SWT.PUSH);
addButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
addButtonSelected();
}
});
addButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
// Edit Dependency button - only if there is a custom Dialog, as the built-in does not need/support this
if (CustomTigerstripeDependenciesManager.hasCustomDialog()) {
editButton = toolkit.createButton(buttonsClient, "Edit...", SWT.PUSH);
editButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
editButtonSelected();
}
});
editButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
}
// Add Missing Transitive Dependency button
// Need to disable this function in the case where the "custom dependency
// Dialog" is set?
if (CustomTigerstripeDependenciesManager.isTransitiveSupported()) {
Button addMissingTransitiveDependenciesButton = toolkit.createButton(buttonsClient, "Add Transitive",
SWT.PUSH);
addMissingTransitiveDependenciesButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
addMissingTransitiveDependenciesButtonSelected();
}
});
addMissingTransitiveDependenciesButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
}
// Remove Dependency button
removeButton = toolkit.createButton(buttonsClient, "Remove", SWT.PUSH);
removeButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
removeButtonSelected();
}
});
removeButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
// Select All button
selectAllButton = toolkit.createButton(buttonsClient, "Select All", SWT.PUSH);
selectAllButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
enableAllDependencies(true);
}
});
selectAllButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
// Deselect All button
deselectAllButton = toolkit.createButton(buttonsClient, "Deselect All", SWT.PUSH);
deselectAllButton.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
disableAllDependencies();
}
});
deselectAllButton.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
viewer = new CheckboxTableViewer(t);
viewer.addSelectionChangedListener(event -> {
updateDetails();
updateButtonsEnablement();
});
viewer.setContentProvider(new ReferencedProjectsContentProvider());
final ITableLabelProvider labelProvider = CustomTigerstripeDependenciesManager.hasCustomLabelProvider()
? CustomTigerstripeDependenciesManager.makeLabelProvider()
: new ReferencedProjectsLabelProvider();
viewer.setLabelProvider(labelProvider);
ITextProvider textAdapter = obj -> labelProvider.getColumnText(obj, 0);
viewer.setComparator(new DependenciesSorter(textAdapter, DEPENDENCY_KIND_RESOLVER));
AbstractTigerstripeProjectHandle handle = (AbstractTigerstripeProjectHandle) getTSProject();
viewer.setInput(handle);
viewer.addCheckStateListener(event -> {
if (!modifyRuntimeDependencies.getSelection()) {
MessageDialog.openInformation(Display.getCurrent().getActiveShell(), "Operation Not Enabled",
"To modify dependencies at generation time (i.e. run generation on certain modules), you'll need to explicitly enable the option below: '"
+ DEP_CHECKBOX_LABEL + "'");
viewer.setChecked(event.getElement(), true);
} else {
getActualTSProject().setDirty();
Object source = event.getElement();
if (source instanceof IDependency) {
((IDependency) source).setEnabled(event.getChecked());
} else if (source instanceof ModelReference) {
((ModelReference) source).setEnabled(event.getChecked());
}
Object input = viewer.getInput();
if (input instanceof TigerstripeProjectHandle) {
((TigerstripeProjectHandle) input).markCacheAsDirty();
}
markPageModified();
}
});
}
protected void editButtonSelected() {
// Need the dialog with everything except the current project in!
// ie INCLUDING current ref, as that's what we want to edit
TableItem[] selectedItems = viewer.getTable().getSelection();
IModelReference selectedReference = null;
if (selectedItems.length > 0) {
Object data = selectedItems[0].getData();
if (data instanceof IModelReference) {
selectedReference = (IModelReference) data;
}
}
List<IModelReference> refList = new ArrayList<IModelReference>();
refList.add(selectedReference);
IProjectSelectionDialog dialog = getDialog(refList);
if (dialog != null) {
dialog.setInitialProjectSelection(selectedReference);
if (selectedReference != null && dialog.open() == Window.OK) {
Object[] results = dialog.getResult();
for (Object res : results) {
String modelId = getModelIdFromResult(res);
if (StringUtils.isNotEmpty(modelId)) {
try {
// Here we need to replace the prior reference with our new one.
// NOTE this can cause duplicates if we are not careful.
getTSProject().removeModelReference(selectedReference.getToModelId());
Map<String, IModelReference> modelRefMap = new HashMap<>();
modelRefMap.put(selectedReference.getToModelId(), selectedReference);
EclipsePlugin.getTigerStripeDependenciesManager().fireRemoveDependencies(getTSProject(),
modelRefMap);
IModelReference ref = null;
for (IModelReference existingRef : getTSProject().getModelReferences()) {
if (StringUtils.equals(existingRef.getToModelId(), modelId)) {
ref = existingRef;
break;
}
}
if (ref == null) {
ref = getTSProject().addModelReference(modelId);
}
viewer.refresh(true);
viewer.setChecked(ref, true); // NM: Check newly added
// dependency
markPageModified();
if (dialog.isIncludeTransitiveDependencies()) {
addMissingTransitiveDependencies(new IModelReference[] { ref });
}
dialog.addDependency();
} catch (TigerstripeException e) {
EclipsePlugin.log(e);
}
}
}
}
viewer.refresh();
}
}
private String getModelIdFromResult(Object res) {
String modelId = null;
if (res instanceof IJavaProject) {
IJavaProject prj = (IJavaProject) res;
ITigerstripeModelProject tsPrj = prj.getProject().getAdapter(ITigerstripeModelProject.class);
if (tsPrj != null) {
try {
modelId = tsPrj.getModelId();
} catch (TigerstripeException e) {
EclipsePlugin.logErrorMessage("Failed to parse model ID from project: " + tsPrj.getName(), e);
}
}
} else if (res instanceof InstalledModule) {
InstalledModule module = (InstalledModule) res;
modelId = module.getModuleID();
} else if (res instanceof String) {
modelId = (String) res;
}
return modelId;
}
protected IProjectSelectionDialog getDialog() {
return getDialog(Collections.emptyList());
}
protected IProjectSelectionDialog getDialog(List<IModelReference> allowedRefs) {
Set<String> filteredOutProjects = new HashSet<>();
try {
// the current project
filteredOutProjects.add(getTSProject().getModelId());
// allowed Refs
for (IModelReference prjRef : getTSProject().getModelReferences()) {
if (!allowedRefs.contains(prjRef)) {
filteredOutProjects.add(prjRef.getToModelId());
}
}
} catch (TigerstripeException e) {
// ignore here
}
// Here we override the default dialog if appropriate extension point is
// implemented
if (CustomTigerstripeDependenciesManager.hasCustomDialog()) {
try {
return CustomTigerstripeDependenciesManager.makeDialog(getSection().getShell(), filteredOutProjects,
getTSProject());
} catch (TigerstripeException e) {
EclipsePlugin.logErrorMessage("Custom Dependencies Dialog Load Error", e);
}
}
return new TigerstripeProjectSelectionDialog(getSection().getShell(), filteredOutProjects, getTSProject());
}
protected void addButtonSelected() {
IProjectSelectionDialog dialog = getDialog();
if (dialog != null && dialog.open() == Window.OK) {
Object[] results = dialog.getResult();
for (Object res : results) {
String modelId = getModelIdFromResult(res);
if (StringUtils.isNotEmpty(modelId)) {
try {
IModelReference ref = null;
for (IModelReference existingRef : getTSProject().getModelReferences()) {
if (StringUtils.equals(existingRef.getToModelId(), modelId)) {
ref = existingRef;
break;
}
}
if (ref == null) {
ref = getTSProject().addModelReference(modelId);
}
viewer.refresh(true);
viewer.setChecked(ref, true); // NM: Check newly added
// dependency
markPageModified();
if (dialog.isIncludeTransitiveDependencies()) {
addMissingTransitiveDependencies(new IModelReference[] { ref });
}
dialog.addDependency();
} catch (TigerstripeException e) {
EclipsePlugin.log(e);
}
continue;
}
if (res instanceof IResource) {
try {
IDependency dep = getTSProject()
.makeDependency(((IResource) res).getProjectRelativePath().toOSString());
getTSProject().addDependency(dep, new NullProgressMonitor());
viewer.refresh(true);
viewer.setChecked(dep, true); // NM: Check newly added
// dependency
markPageModified();
} catch (TigerstripeException e) {
EclipsePlugin.log(e);
}
}
}
}
viewer.refresh();
}
protected void addMissingTransitiveDependenciesButtonSelected() {
// Take the list of current Dependencies and work out
// the list of "missing" transitive" dependencies
// these could be project, or modules
// check for circular/repeats.
// Add the ones found, and highlight any not found in a dialog.
try {
IModelReference[] references = getTSProject().getModelReferences();
addMissingTransitiveDependencies(references);
} catch (TigerstripeException e) {
EclipsePlugin.log(e);
}
}
protected void addMissingTransitiveDependencies(IModelReference[] references) {
try {
Set<String> existingModels = new HashSet<>();
IModelReference[] existingReferences = getTSProject().getModelReferences();
for (IModelReference ref : existingReferences) {
existingModels.add(ref.getToModelId());
}
existingModels.add(getTSProject().getModelId());
List<IModelReference> newRefs = new ArrayList<>();
for (IModelReference ref : references) {
newRefs.addAll(getTransitiveRefs(ref));
}
// deDuplicate
Set<String> referencedModels = new HashSet<>();
for (IModelReference ref : newRefs) {
if (!existingModels.contains(ref.getToModelId())) {
referencedModels.add(ref.getToModelId());
}
}
// set on the model...
for (String ref : referencedModels) {
IModelReference newRef = getTSProject().addModelReference(ref);
if (newRef.getResolvedModel() != null) {
viewer.refresh(true);
viewer.setChecked(newRef, true); // NM: Check newly added
// dependency
markPageModified();
}
}
} catch (TigerstripeException e) {
EclipsePlugin.log(e);
}
}
// recurse on the transitive dependencies
private static List<IModelReference> getTransitiveRefs(IModelReference modelRef) throws TigerstripeException {
List<IModelReference> newRefs = new ArrayList<>();
if (modelRef.getResolvedModel() != null) {
List<IModelReference> addedRefs = Arrays.asList(modelRef.getResolvedModel().getModelReferences());
newRefs.addAll(addedRefs);
for (IModelReference ref : addedRefs) {
if (!newRefs.contains(ref)) {
newRefs.addAll(getTransitiveRefs(ref));
}
}
}
return newRefs;
}
protected void removeButtonSelected() {
TableItem[] selectedItems = viewer.getTable().getSelection();
Map<String, IModelReference> modelRefMap = new HashMap<>();
List<IDependency> dependencyFields = new ArrayList<>();
for (int i = 0; i < selectedItems.length; i++) {
Object data = selectedItems[i].getData();
if (data instanceof IModelReference) {
IModelReference modelRef = (ModelReference) data;
modelRefMap.put(modelRef.getToModelId(), modelRef);
} else if (data instanceof IDependency) {
dependencyFields.add((IDependency) data);
}
}
String message = "Do you really want to remove ";
if (selectedItems.length > 1) {
message = message + "these " + selectedItems.length + " items?";
} else {
message = message + "this item?";
}
MessageDialog msgDialog = new MessageDialog(getBody().getShell(), "Remove Reference/Dependency", null, message,
MessageDialog.QUESTION, new String[] { "Yes", "No" }, 1);
if (msgDialog.open() == 0) {
ITigerstripeModelProjectInternal handle = getTSProject();
try {
handle.removeModelReferences(modelRefMap.keySet().stream().toArray(String[]::new));
handle.removeDependencies(dependencyFields.toArray(new IDependency[0]), new NullProgressMonitor());
} catch (TigerstripeException e) {
EclipsePlugin.log(e);
}
EclipsePlugin.getTigerStripeDependenciesManager().fireRemoveDependencies(getTSProject(), modelRefMap);
markPageModified();
viewer.refresh(true);
}
}
protected void markPageModified() {
DescriptorEditor editor = (DescriptorEditor) getPage().getEditor();
editor.pageModified();
}
@Override
public void refresh() {
if (viewer.getTable().isDisposed()) {
return;
}
updateViewerInput();
updateDetails();
// Don't mark the page as dirty after a refresh.
if (!modifyRuntimeDependencies.getSelection()) {
enableAllDependencies(false);
}
updateButtonsEnablement();
}
private void updateDetails() {
masterDetails.switchTo(((IStructuredSelection) viewer.getSelection()).getFirstElement());
}
private void updateButtonsEnablement() {
TableItem[] selectedItems = viewer.getTable().getSelection();
if (editButton != null) {
editButton.setEnabled(selectedItems != null && selectedItems.length > 0);
}
removeButton.setEnabled(selectedItems != null && selectedItems.length > 0);
}
// [nmehrega] Bugzilla 322566: Update the viewer's input if our working copy
// of TS Project has changed.
// This, for example, happens when the project descriptor is modified and
// saved.
private void updateViewerInput() {
Object tsProjectWorkingCopy = getTSProject();
if (!viewer.getTable().isDisposed()) {
viewer.setInput(tsProjectWorkingCopy);
initializeDependencyEnablement();
}
}
private static final IDependencyKindResolver DEPENDENCY_KIND_RESOLVER = obj -> {
if (obj instanceof ModelReference) {
ModelReference ref = (ModelReference) obj;
if (ref.isResolved()) {
if (ref.isWorkspaceReference()) {
return DependencyKind.PROJECT;
} else if (ref.isInstalledModuleReference()) {
return DependencyKind.MODULE;
}
}
}
if (obj instanceof IDependency) {
return DependencyKind.DEPENDENCY;
}
return DependencyKind.UNKNOWN;
};
public static final DependenciesImageProvider IMAGE_PROVIDER = new DependenciesImageProvider(
DEPENDENCY_KIND_RESOLVER);
}