blob: 6e48578efe64ac3db0400c36784c874622189e62 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2011 SpringSource, a divison of VMware, Inc. 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:
* SpringSource, a division of VMware, Inc. - initial API and implementation
* SAP AG - moving to Eclipse Libra project and enhancements
*******************************************************************************/
package org.eclipse.libra.framework.editor.ui.internal.dependencies;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.libra.framework.editor.core.model.IBundle;
import org.eclipse.libra.framework.editor.core.model.IPackageImport;
import org.eclipse.libra.framework.editor.core.model.IServiceReference;
import org.eclipse.libra.framework.editor.ui.internal.SearchControl;
import org.eclipse.ui.dialogs.SearchPattern;
import org.eclipse.zest.core.viewers.GraphViewer;
import org.eclipse.zest.core.viewers.IGraphContentProvider;
/**
* @author Christian Dupuis
* @author Kaloyan Raev
*/
@SuppressWarnings("restriction")
public class BundleDependencyContentProvider implements IGraphContentProvider, ISelectionChangedListener {
private static final Object[] NO_ELEMENTS = new Object[0];
private Map<Long, IBundle> bundles;
private BundleDependencyContentResult contentResult;
private Map<IBundle, Set<BundleDependency>> dependenciesByBundle;
private int incomingDependencyDegree = 1;
private int outgoingDependencyDegree = 1;
private final SearchControl searchControl;
private Set<BundleDependency> selectedDependencies = new HashSet<BundleDependency>();
private boolean showPackage = true;
private boolean showServices = false;
private final GraphViewer viewer;
private final SearchPattern matcher = new SearchPattern();
public BundleDependencyContentProvider(GraphViewer viewer, SearchControl control) {
this.viewer = viewer;
this.searchControl = control;
}
public void clearSelection() {
for (BundleDependency dep : selectedDependencies) {
viewer.unReveal(dep);
}
selectedDependencies.clear();
for (Object node : viewer.getNodeElements()) {
viewer.update(node, null);
}
for (Object connection : viewer.getConnectionElements()) {
viewer.update(connection, null);
}
}
public void dispose() {
// empty method
}
public BundleDependencyContentResult getContentResult() {
return this.contentResult;
}
public Object getDestination(Object rel) {
if (rel instanceof BundleDependency) {
return ((BundleDependency) rel).getExportingBundle();
}
return null;
}
@SuppressWarnings( { "unchecked" })
public Object[] getElements(Object input) {
if (input instanceof Collection) {
dependenciesByBundle = new HashMap<IBundle, Set<BundleDependency>>();
Set<IBundle> bundleset = new HashSet<IBundle>((Collection<IBundle>) input);
if (!"type filter text".equals(searchControl.getSearchText().getText())
&& searchControl.getSearchText().getText().trim().length() > 0) {
String searchText = searchControl.getSearchText().getText().trim() + "*";
matcher.setPattern(searchText);
for (IBundle dep : new HashSet<IBundle>(bundleset)) {
boolean filter = true;
if (matcher.matches(dep.getSymbolicName())) {
filter = false;
}
if (matcher.matches(dep.getSymbolicName() + " (" + dep.getVersion() + ")")) {
filter = false;
}
if (filter) {
bundleset.remove(dep);
}
}
}
this.contentResult = new BundleDependencyContentResult(bundleset);
Set<BundleDependency> dependencies = new HashSet<BundleDependency>();
if (showPackage) {
Set<IBundle> bundlesToProcess = new HashSet<IBundle>(bundleset);
Set<IBundle> alreadyProcessedBundles = new HashSet<IBundle>();
int degree = 0;
do {
degree++;
Set<IBundle> copy = new HashSet<IBundle>(bundlesToProcess);
bundlesToProcess = new HashSet<IBundle>();
for (IBundle b : copy) {
bundlesToProcess.addAll(addOutgoingPackageDependencies(dependencies, b, degree,
alreadyProcessedBundles));
}
} while (bundlesToProcess.size() > 0);
bundlesToProcess = new HashSet<IBundle>(bundleset);
alreadyProcessedBundles = new HashSet<IBundle>();
degree = 0;
do {
degree++;
Set<IBundle> copy = new HashSet<IBundle>(bundlesToProcess);
bundlesToProcess = new HashSet<IBundle>();
for (IBundle b : copy) {
bundlesToProcess.addAll(addIncomingPackageDependencies(dependencies, b, degree,
alreadyProcessedBundles));
}
} while (bundlesToProcess.size() > 0);
}
else if (showServices) {
Set<IBundle> bundlesToProcess = new HashSet<IBundle>(bundleset);
Set<IBundle> alreadyProcessedBundles = new HashSet<IBundle>();
int degree = 0;
do {
degree++;
Set<IBundle> copy = new HashSet<IBundle>(bundlesToProcess);
bundlesToProcess = new HashSet<IBundle>();
for (IBundle b : copy) {
bundlesToProcess.addAll(addOutgoingServiceDependencies(dependencies, b, degree,
alreadyProcessedBundles));
}
} while (bundlesToProcess.size() > 0);
bundlesToProcess = new HashSet<IBundle>(bundleset);
alreadyProcessedBundles = new HashSet<IBundle>();
degree = 0;
do {
degree++;
Set<IBundle> copy = new HashSet<IBundle>(bundlesToProcess);
bundlesToProcess = new HashSet<IBundle>();
for (IBundle b : copy) {
bundlesToProcess.addAll(addIncomingServiceDependencies(dependencies, b, degree,
alreadyProcessedBundles));
}
} while (bundlesToProcess.size() > 0);
}
if ("type filter text".equals(searchControl.getSearchText().getText())
|| searchControl.getSearchText().getText().trim().length() == 0) {
this.contentResult = null;
}
return dependencies.toArray(new BundleDependency[dependencies.size()]);
}
return NO_ELEMENTS;
}
public Object getSource(Object rel) {
if (rel instanceof BundleDependency) {
return ((BundleDependency) rel).getImportingBundle();
}
return null;
}
public void inputChanged(Viewer theViewer, Object oldInput, Object newInput) {
// empty method
}
public boolean isSelected(IBundle bundle) {
for (BundleDependency dep : selectedDependencies) {
if (dep.getExportingBundle().equals(bundle)) {
return true;
}
}
return false;
}
public boolean isSelected(BundleDependency deb) {
return (selectedDependencies != null && selectedDependencies.contains(deb));
}
@SuppressWarnings("unchecked")
public void selectionChanged(SelectionChangedEvent event) {
for (BundleDependency dep : selectedDependencies) {
viewer.unReveal(dep);
}
selectedDependencies = new HashSet<BundleDependency>();
Iterator<Object> iterator = ((IStructuredSelection) event.getSelection()).iterator();
while (iterator.hasNext()) {
Object selectedObject = iterator.next();
if (selectedObject instanceof IBundle) {
if (dependenciesByBundle.containsKey(selectedObject)) {
for (BundleDependency dep : dependenciesByBundle.get(selectedObject)) {
selectedDependencies.add(dep);
}
}
}
else if (selectedObject instanceof BundleDependency) {
BundleDependency dep = (BundleDependency) selectedObject;
selectedDependencies.add(dep);
}
}
// viewer.setSelection(new StructuredSelection((Object[]) newSelection
// .toArray(new Object[newSelection.size()])), true);
for (Object node : viewer.getNodeElements()) {
viewer.update(node, null);
}
for (Object connection : viewer.getConnectionElements()) {
viewer.update(connection, null);
}
for (BundleDependency dep : selectedDependencies) {
viewer.reveal(dep);
}
// viewer.getGraphControl().redraw();
}
public void setBundles(Map<Long, IBundle> bundles) {
this.bundles = new HashMap<Long, IBundle>(bundles);
}
public void setIncomingDependencyDegree(int degree) {
this.incomingDependencyDegree = degree;
}
public void setOutgoingDependencyDegree(int degree) {
this.outgoingDependencyDegree = degree;
}
public void setShowPackage(boolean showPackage) {
this.showPackage = showPackage;
}
public void setShowServices(boolean showServices) {
this.showServices = showServices;
}
private Set<IBundle> addIncomingPackageDependencies(Set<BundleDependency> dependencies, IBundle bundle, int degree,
Set<IBundle> processedBundles) {
if (processedBundles.contains(bundle)) {
return Collections.emptySet();
}
processedBundles.add(bundle);
Set<IBundle> dependentBundles = new HashSet<IBundle>();
if (incomingDependencyDegree >= degree) {
String id = bundle.getId();
for (IBundle dependantBundle : this.bundles.values()) {
for (IPackageImport packageImport : dependantBundle.getPackageImports()) {
if (packageImport.getSupplierId().equals(id)) {
Set<BundleDependency> bundleDependencies = null;
if (dependenciesByBundle.containsKey(dependantBundle)) {
bundleDependencies = dependenciesByBundle.get(dependantBundle);
}
else {
bundleDependencies = new HashSet<BundleDependency>();
dependenciesByBundle.put(dependantBundle, bundleDependencies);
}
PackageBundleDependency bundleDependency = null;
for (BundleDependency dep : bundleDependencies) {
if (dep.getExportingBundle().equals(bundle) && dep instanceof PackageBundleDependency) {
bundleDependency = (PackageBundleDependency) dep;
break;
}
}
if (bundleDependency == null) {
bundleDependency = new PackageBundleDependency(bundle, dependantBundle);
bundleDependencies.add(bundleDependency);
dependencies.add(bundleDependency);
}
contentResult.addIncomingDependency(Integer.valueOf(degree), dependantBundle);
bundleDependency.addPackageImport(packageImport);
dependentBundles.add(dependantBundle);
}
}
}
}
if (incomingDependencyDegree > degree) {
return dependentBundles;
}
return Collections.emptySet();
}
private Set<IBundle> addIncomingServiceDependencies(Set<BundleDependency> dependencies, IBundle bundle, int degree,
Set<IBundle> processedBundles) {
if (processedBundles.contains(bundle)) {
return Collections.emptySet();
}
processedBundles.add(bundle);
Set<IBundle> dependentBundles = new HashSet<IBundle>();
if (incomingDependencyDegree >= degree) {
for (IServiceReference pe : bundle.getRegisteredServices()) {
for (Long id : pe.getUsingBundleIds()) {
IBundle dependantBundle = this.bundles.get(id);
Set<BundleDependency> bundleDependencies = null;
if (dependenciesByBundle.containsKey(bundle)) {
bundleDependencies = dependenciesByBundle.get(bundle);
}
else {
bundleDependencies = new HashSet<BundleDependency>();
dependenciesByBundle.put(bundle, bundleDependencies);
}
ServiceReferenceBundleDependency bundleDependency = null;
for (BundleDependency dep : bundleDependencies) {
if (dep.getExportingBundle().equals(dependantBundle)
&& dep instanceof ServiceReferenceBundleDependency) {
bundleDependency = (ServiceReferenceBundleDependency) dep;
break;
}
}
if (bundleDependency == null) {
bundleDependency = new ServiceReferenceBundleDependency(bundle, dependantBundle);
bundleDependencies.add(bundleDependency);
dependencies.add(bundleDependency);
}
contentResult.addIncomingDependency(Integer.valueOf(degree), dependantBundle);
bundleDependency.addServiceReferece(pe);
dependentBundles.add(dependantBundle);
}
}
}
if (incomingDependencyDegree > degree) {
return dependentBundles;
}
return Collections.emptySet();
}
private Set<IBundle> addOutgoingPackageDependencies(Set<BundleDependency> dependencies, IBundle bundle, int degree,
Set<IBundle> processedBundles) {
if (processedBundles.contains(bundle)) {
return Collections.emptySet();
}
processedBundles.add(bundle);
Set<IBundle> dependentBundles = new HashSet<IBundle>();
if (outgoingDependencyDegree >= degree) {
for (IPackageImport pe : bundle.getPackageImports()) {
IBundle dependantBundle = this.bundles.get(Long.valueOf(pe.getSupplierId()));
if (dependantBundle == null) {
continue;
}
Set<BundleDependency> bundleDependencies = null;
if (dependenciesByBundle.containsKey(bundle)) {
bundleDependencies = dependenciesByBundle.get(bundle);
}
else {
bundleDependencies = new HashSet<BundleDependency>();
dependenciesByBundle.put(bundle, bundleDependencies);
}
PackageBundleDependency bundleDependency = null;
for (BundleDependency dep : bundleDependencies) {
if (dep.getExportingBundle().equals(dependantBundle) && dep instanceof PackageBundleDependency) {
bundleDependency = (PackageBundleDependency) dep;
break;
}
}
if (bundleDependency == null) {
bundleDependency = new PackageBundleDependency(dependantBundle, bundle);
bundleDependencies.add(bundleDependency);
dependencies.add(bundleDependency);
}
contentResult.addOutgoingDependency(Integer.valueOf(degree), dependantBundle);
bundleDependency.addPackageImport(pe);
dependentBundles.add(dependantBundle);
}
}
if (outgoingDependencyDegree > degree) {
return dependentBundles;
}
return Collections.emptySet();
}
private Set<IBundle> addOutgoingServiceDependencies(Set<BundleDependency> dependencies, IBundle bundle, int degree,
Set<IBundle> processedBundles) {
if (processedBundles.contains(bundle)) {
return Collections.emptySet();
}
processedBundles.add(bundle);
Set<IBundle> dependentBundles = new HashSet<IBundle>();
if (outgoingDependencyDegree >= degree) {
for (IServiceReference pe : bundle.getServicesInUse()) {
IBundle dependantBundle = this.bundles.get(pe.getBundleId());
Set<BundleDependency> bundleDependencies = null;
if (dependenciesByBundle.containsKey(bundle)) {
bundleDependencies = dependenciesByBundle.get(bundle);
}
else {
bundleDependencies = new HashSet<BundleDependency>();
dependenciesByBundle.put(bundle, bundleDependencies);
}
ServiceReferenceBundleDependency bundleDependency = null;
for (BundleDependency dep : bundleDependencies) {
if (dep.getExportingBundle().equals(dependantBundle)
&& dep instanceof ServiceReferenceBundleDependency) {
bundleDependency = (ServiceReferenceBundleDependency) dep;
break;
}
}
if (bundleDependency == null) {
bundleDependency = new ServiceReferenceBundleDependency(dependantBundle, bundle);
bundleDependencies.add(bundleDependency);
dependencies.add(bundleDependency);
}
contentResult.addOutgoingDependency(Integer.valueOf(degree), dependantBundle);
bundleDependency.addServiceReferece(pe);
dependentBundles.add(dependantBundle);
}
}
if (outgoingDependencyDegree > degree) {
return dependentBundles;
}
return Collections.emptySet();
}
}