blob: ef9a6d5e0f2b29516a7aa18972b159c7fb532ce0 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2015, 2018 Obeo.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors: Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.eef.properties.ui.legacy.internal.extension.impl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import org.eclipse.eef.properties.ui.api.IEEFTabDescriptor;
import org.eclipse.eef.properties.ui.legacy.internal.EEFPropertiesUiLegacyPlugin;
import org.eclipse.eef.properties.ui.legacy.internal.extension.IItemDescriptor;
import org.eclipse.eef.properties.ui.legacy.internal.extension.IItemRegistry;
/**
* The registry used to track the descriptors of the property tab extension.
*
* @author mbats
*/
public class LegacyPropertyTabRegistry implements IItemRegistry {
/**
* The after tab top value.
*/
private static final String TOP = "top"; //$NON-NLS-1$
/**
* The map of the identifier of the description to the {@link LegacyPropertyTabItemDescriptor}.
*/
private Map<String, List<IItemDescriptor>> id2descriptors = new HashMap<>();
/**
* Get the property tabs.
*
* @param contributorId
* The contributor Id
*
* @return List of tabs
*/
public List<IEEFTabDescriptor> getPropertyTabs(String contributorId) {
// Get tabs
List<IEEFTabDescriptor> tabs = readTabDescriptors(contributorId);
// Get categories
final List<String> propertyCategories = readPropertyCategories();
// Sort the tabs according to their categories
List<IEEFTabDescriptor> sortedTabs = sortTabDescriptorsByCategory(tabs, propertyCategories);
// Sort the tabs according to the after tab attribute
sortedTabs = sortTabDescriptorsByAfterTab(sortedTabs, propertyCategories);
return sortedTabs;
}
/**
* Sorts the tab descriptors in the given list according to category.
*
* @param tabs
* Tabs to sort
* @param propertyCategories
* Property categories
* @return Sorted list of tabs according to there categories
*/
private List<IEEFTabDescriptor> sortTabDescriptorsByCategory(List<IEEFTabDescriptor> tabs, final List<String> propertyCategories) {
List<IEEFTabDescriptor> sortedTabs = new ArrayList<IEEFTabDescriptor>(tabs);
if (propertyCategories != null) {
Collections.sort(sortedTabs, new Comparator<Object>() {
@Override
public int compare(Object arg0, Object arg1) {
IEEFTabDescriptor one = (IEEFTabDescriptor) arg0;
IEEFTabDescriptor two = (IEEFTabDescriptor) arg1;
String categoryOne = one.getCategory();
String categoryTwo = two.getCategory();
if (categoryOne != null && categoryTwo != null) {
int categoryOnePosition = getIndex(propertyCategories.toArray(), categoryOne);
int categoryTwoPosition = getIndex(propertyCategories.toArray(), categoryTwo);
return categoryOnePosition - categoryTwoPosition;
}
return 0;
}
});
}
return sortedTabs;
}
/**
* Sorts the tab descriptors in the given list according to afterTab.
*
* @param tabs
* Tabs to sort
* @param propertyCategories
* Property categories
* @return Sorted list of tabs according to the afterTab attribute
*/
private List<IEEFTabDescriptor> sortTabDescriptorsByAfterTab(List<IEEFTabDescriptor> tabs, List<String> propertyCategories) {
if (tabs.size() == 0 || propertyCategories == null) {
return tabs;
}
List<IEEFTabDescriptor> sorted = new ArrayList<IEEFTabDescriptor>();
int categoryIndex = 0;
for (int i = 0; i < propertyCategories.size(); i++) {
// Get all the tabs of a category
final List<IEEFTabDescriptor> categoryList = new ArrayList<IEEFTabDescriptor>();
String category = propertyCategories.get(i);
int topOfCategory = categoryIndex;
int endOfCategory = categoryIndex;
while (endOfCategory < tabs.size() && tabs.get(endOfCategory).getCategory().equals(category)) {
endOfCategory++;
}
for (int j = topOfCategory; j < endOfCategory; j++) {
IEEFTabDescriptor tab = tabs.get(j);
if (tab.getAfterTab().equals(TOP)) {
categoryList.add(0, tabs.get(j));
} else {
categoryList.add(tabs.get(j));
}
}
List<IEEFTabDescriptor> sortedTabs = sortCategoryTabsByAfterTab(categoryList);
for (int j = 0; j < sortedTabs.size(); j++) {
sorted.add(sortedTabs.get(j));
}
categoryIndex = endOfCategory;
}
return sorted;
}
/**
* Sort tabs of a category by after tab.
*
* @param categoryList
* List of tabs
* @return List of tabs sorted by after tab
*/
private List<IEEFTabDescriptor> sortCategoryTabsByAfterTab(List<IEEFTabDescriptor> categoryList) {
List<IEEFTabDescriptor> sorted = new LinkedList<IEEFTabDescriptor>();
for (IEEFTabDescriptor tab : categoryList) {
String afterTabId = tab.getAfterTab();
int indexOfAfterTab = -1;
if (afterTabId != null && !afterTabId.isEmpty()) {
IEEFTabDescriptor afterTab = getTab(categoryList, afterTabId);
if (afterTab != null) {
indexOfAfterTab = sorted.indexOf(afterTab);
}
}
sorted.add(indexOfAfterTab + 1, tab);
}
return sorted;
}
/**
* Get a tab in a list of tabs according to its id.
*
* @param tabId
* The tab id
* @param tabs
* The tabs list
* @return the Tab
*/
private IEEFTabDescriptor getTab(List<IEEFTabDescriptor> tabs, String tabId) {
for (IEEFTabDescriptor tab : tabs) {
if (tabId.equals(tab.getId())) {
return tab;
}
}
return null;
}
/**
* Returns the index of the given element in the array.
*
* @param array
* Array
* @param target
* The element to search
* @return The index of the searched element in the array if it exists otherwise -1
*/
private int getIndex(Object[] array, Object target) {
for (int i = 0; i < array.length; i++) {
if (target != null && array[i] != null && array[i].equals(target)) {
return i;
}
}
return -1; // should never happen
}
/**
* Read property categories from the extension point.
*
* @return List of categories
*/
private List<String> readPropertyCategories() {
return EEFPropertiesUiLegacyPlugin.getImplementation().getTabbedPropertyContributorRegistry().getPropertyCategories();
}
/**
* Reads property tab extensions. Returns all tab descriptors for the current contributor id or an empty list if
* none is found.
*
* @param contributorId
* The contributor id
*
* @return List of static tab descriptors
*/
private List<IEEFTabDescriptor> readTabDescriptors(String contributorId) {
List<IEEFTabDescriptor> eefTabDescriptors = new ArrayList<IEEFTabDescriptor>();
// @formatter:off
Collection<IItemDescriptor> values = this.id2descriptors.values().stream()
.filter(Objects::nonNull)
.flatMap(List::stream)
.collect(Collectors.toList());
// @formatter:on
for (IItemDescriptor itemDescriptor : values) {
if (itemDescriptor instanceof LegacyPropertyTabItemDescriptor) {
LegacyPropertyTabItemDescriptor eefTabDescriptor = (LegacyPropertyTabItemDescriptor) itemDescriptor;
String eefTabContributorId = eefTabDescriptor.getContributorId();
if (eefTabContributorId != null && eefTabContributorId.equals(contributorId)) {
eefTabDescriptors.add(eefTabDescriptor);
}
}
}
return eefTabDescriptors;
}
/**
* {@inheritDoc}
*
* @see IItemRegistry#add(IItemDescriptor)
*/
@Override
public IItemDescriptor add(IItemDescriptor descriptor) {
List<IItemDescriptor> descriptors = this.id2descriptors.getOrDefault(descriptor.getId(), new ArrayList<>());
boolean result = descriptors.add(descriptor);
this.id2descriptors.put(descriptor.getId(), descriptors);
if (result) {
return descriptor;
}
return null;
}
/**
* {@inheritDoc}
*
* @see IItemRegistry#add(IItemDescriptor)
*/
@Override
public boolean remove(String id) {
List<IItemDescriptor> descriptors = Optional.ofNullable(this.id2descriptors.remove(id)).orElseGet(ArrayList::new);
return !descriptors.isEmpty();
}
/**
* {@inheritDoc}
*
* @see IItemRegistry#clear()
*/
@Override
public void clear() {
this.id2descriptors.clear();
}
/**
* Disposes this registry.
*/
public void dispose() {
// @formatter:off
this.id2descriptors.values().stream()
.filter(Objects::nonNull)
.flatMap(List::stream)
.filter(LegacyPropertyTabItemDescriptor.class::isInstance)
.map(LegacyPropertyTabItemDescriptor.class::cast)
.forEach(LegacyPropertyTabItemDescriptor::dispose);
// @formatter:on
}
}