package bndtools.model.resolution; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import org.eclipse.jface.viewers.ITreeContentProvider; import org.eclipse.jface.viewers.Viewer; import org.osgi.framework.namespace.BundleNamespace; import org.osgi.framework.namespace.HostNamespace; import org.osgi.framework.namespace.IdentityNamespace; import org.osgi.framework.namespace.PackageNamespace; public class CapReqMapContentProvider implements ITreeContentProvider { private static final Object[] EMPTY = new Object[0]; private static final String[] NAMESPACE_ORDER = new String[] { BundleNamespace.BUNDLE_NAMESPACE, IdentityNamespace.IDENTITY_NAMESPACE, HostNamespace.HOST_NAMESPACE, PackageNamespace.PACKAGE_NAMESPACE }; private static final Set<String> NAMESPACES; private final Comparator<Object> comparator = new CapReqComparator(); static { NAMESPACES = new HashSet<>(); for (String s : NAMESPACE_ORDER) NAMESPACES.add(s); } @Override public void dispose() {} @Override public void inputChanged(Viewer viewer, Object oldValue, Object newValue) {} @Override public Object[] getElements(Object input) { List<Object[]> arrays = new LinkedList<>(); @SuppressWarnings("unchecked") Map<String,List<Object>> map = (Map<String,List<Object>>) input; // Add entries for our preferred ordering of namespaces for (String namespace : NAMESPACE_ORDER) { List<Object> listForNs = map.get(namespace); if (listForNs != null) { Object[] array = listForNs.toArray(); Arrays.sort(array, comparator); arrays.add(array); } } // Now the rest in any order for (Entry<String,List<Object>> entry : map.entrySet()) { // Skip if namespace is a member of the namespaces we have already added. if (NAMESPACES.contains(entry.getKey())) continue; List<Object> listForNs = entry.getValue(); Object[] array = listForNs.toArray(); Arrays.sort(array, comparator); arrays.add(array); } return flatten(arrays); } private Object[] flatten(List<Object[]> arrays) { // Iterate over once to count the lengths int length = 0; for (Object[] array : arrays) { length += array.length; } Object[] result = new Object[length]; // Iterate again to flatten out the arrays int position = 0; for (Object[] array : arrays) { System.arraycopy(array, 0, result, position, array.length); position += array.length; } return result; } @Override public Object getParent(Object object) { return null; } @Override public boolean hasChildren(Object object) { boolean children = false; if (object instanceof RequirementWrapper) { RequirementWrapper rw = (RequirementWrapper) object; children = rw.requirers != null && !rw.requirers.isEmpty(); } return children; } @Override public Object[] getChildren(Object parent) { Object[] result = EMPTY; if (parent instanceof RequirementWrapper) { Collection< ? extends Object> requirers = ((RequirementWrapper) parent).requirers; if (requirers != null) result = requirers.toArray(); } return result; } }