blob: 76583766d71160b8b26838c725013e53ed2e409b [file] [log] [blame]
/*
* Copyright (c) 2014-2017 Eike Stepper (Loehne, Germany) and others.
* 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
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* Eike Stepper - initial API and implementation
*/
package org.eclipse.oomph.setup.targlets.provider;
import org.eclipse.oomph.p2.Configuration;
import org.eclipse.oomph.p2.P2Factory;
import org.eclipse.oomph.p2.Repository;
import org.eclipse.oomph.p2.RepositoryList;
import org.eclipse.oomph.p2.Requirement;
import org.eclipse.oomph.p2.core.P2Util;
import org.eclipse.oomph.resources.ResourcesFactory;
import org.eclipse.oomph.resources.SourceLocator;
import org.eclipse.oomph.setup.Project;
import org.eclipse.oomph.setup.ProjectCatalog;
import org.eclipse.oomph.setup.Scope;
import org.eclipse.oomph.setup.SetupTask;
import org.eclipse.oomph.setup.VariableChoice;
import org.eclipse.oomph.setup.VariableTask;
import org.eclipse.oomph.setup.provider.SetupTaskItemProvider;
import org.eclipse.oomph.setup.targlets.SetupTargletsFactory;
import org.eclipse.oomph.setup.targlets.SetupTargletsPackage;
import org.eclipse.oomph.setup.targlets.TargletTask;
import org.eclipse.oomph.targlets.IUGenerator;
import org.eclipse.oomph.targlets.Targlet;
import org.eclipse.oomph.targlets.TargletFactory;
import org.eclipse.oomph.targlets.core.WorkspaceIUInfo;
import org.eclipse.oomph.targlets.internal.core.WorkspaceIUAnalyzer;
import org.eclipse.oomph.util.ReflectUtil;
import org.eclipse.oomph.util.StringUtil;
import org.eclipse.oomph.util.pde.TargetPlatformRunnable;
import org.eclipse.oomph.util.pde.TargetPlatformUtil;
import org.eclipse.emf.common.command.Command;
import org.eclipse.emf.common.command.CompoundCommand;
import org.eclipse.emf.common.command.IdentityCommand;
import org.eclipse.emf.common.notify.AdapterFactory;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.ResourceLocator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
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.command.AddCommand;
import org.eclipse.emf.edit.command.CommandParameter;
import org.eclipse.emf.edit.command.DeleteCommand;
import org.eclipse.emf.edit.command.DragAndDropCommand;
import org.eclipse.emf.edit.command.SetCommand;
import org.eclipse.emf.edit.domain.EditingDomain;
import org.eclipse.emf.edit.provider.AdapterFactoryItemDelegator;
import org.eclipse.emf.edit.provider.ComposeableAdapterFactory;
import org.eclipse.emf.edit.provider.IItemLabelProvider;
import org.eclipse.emf.edit.provider.IItemPropertyDescriptor;
import org.eclipse.emf.edit.provider.ItemPropertyDescriptor;
import org.eclipse.emf.edit.provider.ViewerNotification;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.equinox.p2.metadata.IInstallableUnit;
import org.eclipse.equinox.p2.metadata.IRequirement;
import org.eclipse.equinox.p2.metadata.Version;
import org.eclipse.equinox.p2.metadata.expression.IMatchExpression;
import org.eclipse.equinox.p2.query.CollectionResult;
import org.eclipse.equinox.p2.query.IQueryable;
import org.eclipse.equinox.p2.query.QueryUtil;
import org.eclipse.pde.core.target.ITargetDefinition;
import org.eclipse.pde.core.target.ITargetHandle;
import org.eclipse.pde.core.target.ITargetLocation;
import org.eclipse.pde.core.target.ITargetPlatformService;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* This is the item provider adapter for a {@link org.eclipse.oomph.setup.targlets.TargletTask} object.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public class TargletTaskItemProvider extends SetupTaskItemProvider
{
private static final Pattern VERSION_PATTERN = Pattern.compile("([1-9]+\\.[0-9]+)");
/**
* This constructs an instance from a factory and a notifier.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
public TargletTaskItemProvider(AdapterFactory adapterFactory)
{
super(adapterFactory);
}
/**
* This returns the property descriptors for the adapted class.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public List<IItemPropertyDescriptor> getPropertyDescriptors(Object object)
{
if (itemPropertyDescriptors == null)
{
super.getPropertyDescriptors(object);
addTargletURIsPropertyDescriptor(object);
addOperatingSystemPropertyDescriptor(object);
addWindowingSystemPropertyDescriptor(object);
addArchitecturePropertyDescriptor(object);
addLocalePropertyDescriptor(object);
addProgramArgumentsPropertyDescriptor(object);
addVMArgumentsPropertyDescriptor(object);
addTargetNamePropertyDescriptor(object);
addActivateTargetPropertyDescriptor(object);
}
return itemPropertyDescriptors;
}
/**
* This adds a property descriptor for the Target Name feature.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected void addTargetNamePropertyDescriptor(Object object)
{
itemPropertyDescriptors.add(createItemPropertyDescriptor(((ComposeableAdapterFactory)adapterFactory).getRootAdapterFactory(), getResourceLocator(),
getString("_UI_TargletTask_targetName_feature"),
getString("_UI_PropertyDescriptor_description", "_UI_TargletTask_targetName_feature", "_UI_TargletTask_type"),
SetupTargletsPackage.Literals.TARGLET_TASK__TARGET_NAME, true, false, false, ItemPropertyDescriptor.GENERIC_VALUE_IMAGE, null, null));
}
/**
* This adds a property descriptor for the Activate Target feature.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected void addActivateTargetPropertyDescriptor(Object object)
{
itemPropertyDescriptors.add(createItemPropertyDescriptor(((ComposeableAdapterFactory)adapterFactory).getRootAdapterFactory(), getResourceLocator(),
getString("_UI_TargletTask_activateTarget_feature"),
getString("_UI_PropertyDescriptor_description", "_UI_TargletTask_activateTarget_feature", "_UI_TargletTask_type"),
SetupTargletsPackage.Literals.TARGLET_TASK__ACTIVATE_TARGET, true, false, false, ItemPropertyDescriptor.BOOLEAN_VALUE_IMAGE, null, null));
}
/**
* This adds a property descriptor for the Targlet UR Is feature.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected void addTargletURIsPropertyDescriptor(Object object)
{
itemPropertyDescriptors.add(createItemPropertyDescriptor(((ComposeableAdapterFactory)adapterFactory).getRootAdapterFactory(), getResourceLocator(),
getString("_UI_TargletTask_targletURIs_feature"),
getString("_UI_PropertyDescriptor_description", "_UI_TargletTask_targletURIs_feature", "_UI_TargletTask_type"),
SetupTargletsPackage.Literals.TARGLET_TASK__TARGLET_UR_IS, true, false, false, ItemPropertyDescriptor.GENERIC_VALUE_IMAGE, null, null));
}
/**
* This adds a property descriptor for the Operating System feature.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
protected void addOperatingSystemPropertyDescriptor(Object object)
{
itemPropertyDescriptors.add(new ItemPropertyDescriptor(((ComposeableAdapterFactory)adapterFactory).getRootAdapterFactory(), getResourceLocator(),
getString("_UI_TargletTask_operatingSystem_feature"),
getString("_UI_PropertyDescriptor_description", "_UI_TargletTask_operatingSystem_feature", "_UI_TargletTask_type"),
SetupTargletsPackage.Literals.TARGLET_TASK__OPERATING_SYSTEM, true, false, true, ItemPropertyDescriptor.GENERIC_VALUE_IMAGE, null, null)
{
@Override
public Collection<?> getChoiceOfValues(Object object)
{
return Configuration.Choices.forOS();
}
});
}
/**
* This adds a property descriptor for the Windowing System feature.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
protected void addWindowingSystemPropertyDescriptor(Object object)
{
itemPropertyDescriptors.add(new ItemPropertyDescriptor(((ComposeableAdapterFactory)adapterFactory).getRootAdapterFactory(), getResourceLocator(),
getString("_UI_TargletTask_windowingSystem_feature"),
getString("_UI_PropertyDescriptor_description", "_UI_TargletTask_windowingSystem_feature", "_UI_TargletTask_type"),
SetupTargletsPackage.Literals.TARGLET_TASK__WINDOWING_SYSTEM, true, false, true, ItemPropertyDescriptor.GENERIC_VALUE_IMAGE, null, null)
{
@Override
public Collection<?> getChoiceOfValues(Object object)
{
return Configuration.Choices.forWS();
}
});
}
/**
* This adds a property descriptor for the Architecture feature.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
protected void addArchitecturePropertyDescriptor(Object object)
{
itemPropertyDescriptors.add(new ItemPropertyDescriptor(((ComposeableAdapterFactory)adapterFactory).getRootAdapterFactory(), getResourceLocator(),
getString("_UI_TargletTask_architecture_feature"),
getString("_UI_PropertyDescriptor_description", "_UI_TargletTask_architecture_feature", "_UI_TargletTask_type"),
SetupTargletsPackage.Literals.TARGLET_TASK__ARCHITECTURE, true, false, true, ItemPropertyDescriptor.GENERIC_VALUE_IMAGE, null, null)
{
@Override
public Collection<?> getChoiceOfValues(Object object)
{
return Configuration.Choices.forArch();
}
});
}
/**
* This adds a property descriptor for the Locale feature.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
protected void addLocalePropertyDescriptor(Object object)
{
itemPropertyDescriptors.add(new ItemPropertyDescriptor(((ComposeableAdapterFactory)adapterFactory).getRootAdapterFactory(), getResourceLocator(),
getString("_UI_TargletTask_locale_feature"), getString("_UI_PropertyDescriptor_description", "_UI_TargletTask_locale_feature", "_UI_TargletTask_type"),
SetupTargletsPackage.Literals.TARGLET_TASK__LOCALE, true, false, true, ItemPropertyDescriptor.GENERIC_VALUE_IMAGE, null, null)
{
private static final String NL_EXTRA = "org.eclipse.pde.nl.extra";
private LocaleItemLabelProvider labelProvider;
@Override
public Collection<?> getChoiceOfValues(Object object)
{
LocaleItemLabelProvider labelProvider = getLabelProvider(object);
Set<String> locales = labelProvider.getLocaleMap().keySet();
return getChoices(locales.toArray(new String[locales.size()]), NL_EXTRA);
}
@Override
public LocaleItemLabelProvider getLabelProvider(Object object)
{
if (labelProvider == null)
{
labelProvider = new LocaleItemLabelProvider(itemDelegator);
}
return labelProvider;
}
});
}
/**
* This adds a property descriptor for the Program Arguments feature.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected void addProgramArgumentsPropertyDescriptor(Object object)
{
itemPropertyDescriptors.add(createItemPropertyDescriptor(((ComposeableAdapterFactory)adapterFactory).getRootAdapterFactory(), getResourceLocator(),
getString("_UI_TargletTask_programArguments_feature"),
getString("_UI_PropertyDescriptor_description", "_UI_TargletTask_programArguments_feature", "_UI_TargletTask_type"),
SetupTargletsPackage.Literals.TARGLET_TASK__PROGRAM_ARGUMENTS, true, true, false, ItemPropertyDescriptor.GENERIC_VALUE_IMAGE, null, null));
}
/**
* This adds a property descriptor for the VM Arguments feature.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
protected void addVMArgumentsPropertyDescriptor(Object object)
{
itemPropertyDescriptors.add(createItemPropertyDescriptor(((ComposeableAdapterFactory)adapterFactory).getRootAdapterFactory(), getResourceLocator(),
getString("_UI_TargletTask_vMArguments_feature"),
getString("_UI_PropertyDescriptor_description", "_UI_TargletTask_vMArguments_feature", "_UI_TargletTask_type"),
SetupTargletsPackage.Literals.TARGLET_TASK__VM_ARGUMENTS, true, true, false, ItemPropertyDescriptor.GENERIC_VALUE_IMAGE, null, null));
}
private static Set<String> getChoices(String[] values, String extraValuesPreference)
{
Set<String> result = new HashSet<String>();
result.addAll(Arrays.asList(values));
IEclipsePreferences node = InstanceScope.INSTANCE.getNode("org.eclipse.pde.core");
String extraValues = node.get(extraValuesPreference, null);
if (!StringUtil.isEmpty(extraValues))
{
StringTokenizer tokenizer = new StringTokenizer(extraValues, ",");
while (tokenizer.hasMoreTokens())
{
String extraValue = tokenizer.nextToken().trim();
result.add(extraValue);
}
}
return result;
}
/**
* This specifies how to implement {@link #getChildren} and is used to deduce an appropriate feature for an
* {@link org.eclipse.emf.edit.command.AddCommand}, {@link org.eclipse.emf.edit.command.RemoveCommand} or
* {@link org.eclipse.emf.edit.command.MoveCommand} in {@link #createCommand}.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Collection<? extends EStructuralFeature> getChildrenFeatures(Object object)
{
if (childrenFeatures == null)
{
super.getChildrenFeatures(object);
childrenFeatures.add(SetupTargletsPackage.Literals.TARGLET_TASK__TARGLETS);
childrenFeatures.add(SetupTargletsPackage.Literals.TARGLET_TASK__IMPLICIT_DEPENDENCIES);
}
return childrenFeatures;
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected EStructuralFeature getChildFeature(Object object, Object child)
{
// Check the type of the specified child object and return the proper feature to use for
// adding (see {@link AddCommand}) it as a child.
return super.getChildFeature(object, child);
}
/**
* This returns TargletTask.gif.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public Object getImage(Object object)
{
return overlayImage(object, getResourceLocator().getImage("full/obj16/TargletTask"));
}
/**
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected boolean shouldComposeCreationImage()
{
return true;
}
/**
* This returns the label text for the adapted class.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated NOT
*/
@Override
public String getText(Object object)
{
TargletTask targletTask = (TargletTask)object;
StringBuilder builder = new StringBuilder();
Set<String> added = new HashSet<String>();
String targetNameLabel = "";
String targetName = targletTask.getTargetName();
if (targetName != null)
{
Pattern TARGET_NAME_LABEL_PATTERN = Pattern.compile("(.*)[\\s-_](Modular)?[\\s-_]*(Target)?");
Matcher matcher = TARGET_NAME_LABEL_PATTERN.matcher(targetName);
if (matcher.matches())
{
targetNameLabel = matcher.group(1);
}
else
{
targetNameLabel = targetName;
}
}
for (Targlet targlet : targletTask.getTarglets())
{
String name = targlet.getName();
if (added.add(name))
{
if (builder.length() != 0)
{
builder.append(" + ");
}
builder.append(name);
}
}
if (builder.length() != 0)
{
builder.insert(0, " (");
builder.append(')');
}
if (StringUtil.isEmpty(targetNameLabel))
{
builder.insert(0, "Target");
}
else
{
builder.insert(0, " Target");
builder.insert(0, targetNameLabel);
}
if (targletTask.isActivateTarget())
{
builder.append(", activate");
}
return builder.toString();
}
/**
* This handles model notifications by calling {@link #updateChildren} to update any cached
* children and by creating a viewer notification, which it passes to {@link #fireNotifyChanged}.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public void notifyChanged(Notification notification)
{
updateChildren(notification);
switch (notification.getFeatureID(TargletTask.class))
{
case SetupTargletsPackage.TARGLET_TASK__TARGLET_UR_IS:
case SetupTargletsPackage.TARGLET_TASK__OPERATING_SYSTEM:
case SetupTargletsPackage.TARGLET_TASK__WINDOWING_SYSTEM:
case SetupTargletsPackage.TARGLET_TASK__ARCHITECTURE:
case SetupTargletsPackage.TARGLET_TASK__LOCALE:
case SetupTargletsPackage.TARGLET_TASK__PROGRAM_ARGUMENTS:
case SetupTargletsPackage.TARGLET_TASK__VM_ARGUMENTS:
case SetupTargletsPackage.TARGLET_TASK__TARGET_NAME:
case SetupTargletsPackage.TARGLET_TASK__ACTIVATE_TARGET:
fireNotifyChanged(new ViewerNotification(notification, notification.getNotifier(), false, true));
return;
case SetupTargletsPackage.TARGLET_TASK__TARGLETS:
case SetupTargletsPackage.TARGLET_TASK__IMPLICIT_DEPENDENCIES:
fireNotifyChanged(new ViewerNotification(notification, notification.getNotifier(), true, false));
return;
}
super.notifyChanged(notification);
}
/**
* This adds {@link org.eclipse.emf.edit.command.CommandParameter}s describing the children
* that can be created under this object.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
protected void collectNewChildDescriptors(Collection<Object> newChildDescriptors, Object object)
{
super.collectNewChildDescriptors(newChildDescriptors, object);
newChildDescriptors.add(createChildParameter(SetupTargletsPackage.Literals.TARGLET_TASK__TARGLETS, TargletFactory.eINSTANCE.createTarglet()));
newChildDescriptors.add(
createChildParameter(SetupTargletsPackage.Literals.TARGLET_TASK__IMPLICIT_DEPENDENCIES, SetupTargletsFactory.eINSTANCE.createImplicitDependency()));
}
@Override
public Command createCommand(Object object, final EditingDomain domain, Class<? extends Command> commandClass, final CommandParameter commandParameter)
{
if (commandClass == DragAndDropCommand.class)
{
// Determine if we've dragged a *.target file from the workspace.
Collection<?> collection = commandParameter.getCollection();
if (collection.size() == 1)
{
Object value = collection.iterator().next();
if (value instanceof URI)
{
final URI uri = (URI)value;
if ("target".equals(uri.fileExtension()) && uri.isPlatformResource())
{
final Path path = new Path(uri.toPlatformString(true));
try
{
// Use PDE to analyze the syntactic contents of this *.target file.
Command result = TargetPlatformUtil.runWithTargetPlatformService(new TargetPlatformRunnable<Command>()
{
@SuppressWarnings("restriction")
public Command run(ITargetPlatformService service) throws CoreException
{
// Consider all the target handles available to PDE.
for (ITargetHandle targetHandle : service.getTargets(new NullProgressMonitor()))
{
// If it has a workspace handle...
if (targetHandle instanceof org.eclipse.pde.internal.core.target.WorkspaceFileTargetHandle)
{
// And that workspace handle is the one for the file that's been dragged...
org.eclipse.pde.internal.core.target.WorkspaceFileTargetHandle workspaceFileTargetHandle = (org.eclipse.pde.internal.core.target.WorkspaceFileTargetHandle)targetHandle;
IFile targetFile = workspaceFileTargetHandle.getTargetFile();
if (path.equals(targetFile.getFullPath()))
{
// Maintain the requirements in a sorted list.
final Set<Requirement> requirements = new TreeSet<Requirement>(new Comparator<Requirement>()
{
public int compare(Requirement requirement1, Requirement requirement2)
{
String name1 = requirement1.getName();
String name2 = requirement2.getName();
return name1.compareTo(name2);
}
});
// Maintain the repositories in a sorted list.
final Set<Repository> repos = new TreeSet<Repository>(new Comparator<Repository>()
{
public int compare(Repository repository1, Repository repository2)
{
String url1 = repository1.getURL();
String url2 = repository2.getURL();
return url1.compareTo(url2);
}
});
// Get the target definition as its important attributes.
ITargetDefinition targetDefinition = targetHandle.getTargetDefinition();
final String arch = targetDefinition.getArch();
final String os = targetDefinition.getOS();
final String ws = targetDefinition.getWS();
final String nl = targetDefinition.getNL();
final String programArguments = targetDefinition.getProgramArguments();
final String vmArguments = targetDefinition.getVMArguments();
// Consider each target location, and an IU bundle container.
ITargetLocation[] targetLocations = targetDefinition.getTargetLocations();
if (targetLocations != null)
{
for (ITargetLocation targetLocation : targetLocations)
{
if (targetLocation instanceof org.eclipse.pde.internal.core.target.IUBundleContainer)
{
org.eclipse.pde.internal.core.target.IUBundleContainer iuBundleContainer = (org.eclipse.pde.internal.core.target.IUBundleContainer)targetLocation;
// Create a repository for each repository of that container.
java.net.URI[] repositories = iuBundleContainer.getRepositories();
for (java.net.URI repo : repositories)
{
URI repoURI = URI.createURI(repo.toString());
if (repoURI.hasTrailingPathSeparator())
{
repoURI = repoURI.trimSegments(1);
}
repos.add(P2Factory.eINSTANCE.createRepository(repoURI.toString()));
}
// Reflectively get the underlying IDs and Versions.
String[] ids = (String[])ReflectUtil.invokeMethod("getIds", iuBundleContainer);
Version[] versions = (Version[])ReflectUtil.invokeMethod("getVersions", iuBundleContainer);
for (int i = 0, length = ids.length; i < length; ++i)
{
requirements.add(P2Factory.eINSTANCE.createRequirement(ids[i], versions[i]));
}
}
}
}
// Create a drag and drop command for this information.
DragAndDropCommand.Detail detail = (DragAndDropCommand.Detail)commandParameter.getFeature();
return new TargletDragAndDropCommand(domain, commandParameter.getOwner(), detail.location, detail.operations, detail.operation,
commandParameter.getCollection())
{
@Override
protected boolean prepareDropCopyOn()
{
dragCommand = IdentityCommand.INSTANCE;
CompoundCommand compoundCommand = new CompoundCommand(0);
dropCommand = compoundCommand;
// Always create a new targlet, but name it to reflect that it represents a target platform.
Targlet targlet = TargletFactory.eINSTANCE.createTarglet();
targlet.setName(getTargletName(StringUtil.cap(uri.trimFileExtension().lastSegment())) + "Target Platform");
// Use the standard variable to refer to the active repository.
targlet.setActiveRepositoryListName("${eclipse.target.platform}");
// Add all the requirements to the new targlet.
targlet.getRequirements().addAll(requirements);
// Create a new repository list, try to determine standard name for it, and all the the repos to it.
EList<RepositoryList> repositoryLists = targlet.getRepositoryLists();
RepositoryList repositoryList = P2Factory.eINSTANCE.createRepositoryList();
repositoryList.setName(getRepositoryListName(StringUtil.cap(uri.trimFileExtension().lastSegment())));
repositoryLists.add(repositoryList);
repositoryList.getRepositories().addAll(repos);
TargletTask targletTask = (TargletTask)owner;
// Create a command to add the new targlet.
compoundCommand.append(new AddCommand(domain, targletTask, SetupTargletsPackage.Literals.TARGLET_TASK__TARGLETS, targlet));
// Set the architecture if there is one.
if (StringUtil.isEmpty(targletTask.getArchitecture()) && !StringUtil.isEmpty(arch))
{
compoundCommand.append(new SetCommand(domain, targletTask, SetupTargletsPackage.Literals.TARGLET_TASK__ARCHITECTURE, arch));
}
// Set the operating system if there is one.
if (StringUtil.isEmpty(targletTask.getOperatingSystem()) && !StringUtil.isEmpty(os))
{
compoundCommand.append(new SetCommand(domain, targletTask, SetupTargletsPackage.Literals.TARGLET_TASK__OPERATING_SYSTEM, os));
}
// Set the windowing system if there is one.
if (StringUtil.isEmpty(targletTask.getWindowingSystem()) && !StringUtil.isEmpty(ws))
{
compoundCommand.append(new SetCommand(domain, targletTask, SetupTargletsPackage.Literals.TARGLET_TASK__WINDOWING_SYSTEM, ws));
}
// Set the locale if there is one.
if (StringUtil.isEmpty(targletTask.getLocale()) && !StringUtil.isEmpty(nl))
{
compoundCommand.append(new SetCommand(domain, targletTask, SetupTargletsPackage.Literals.TARGLET_TASK__LOCALE, nl));
}
// Compose the VM arguments if the are any.
if (!StringUtil.isEmpty(vmArguments))
{
String newVmArguments = targletTask.getVMArguments();
if (StringUtil.isEmpty(newVmArguments))
{
newVmArguments = "";
}
else
{
newVmArguments += "\n";
}
newVmArguments += vmArguments;
compoundCommand.append(new SetCommand(domain, targletTask, SetupTargletsPackage.Literals.TARGLET_TASK__VM_ARGUMENTS,
newVmArguments.replaceAll("[\n\r]+", "\n").trim()));
}
// Compose the program arguments if the are any.
if (!StringUtil.isEmpty(programArguments))
{
String newProgramArguments = targletTask.getProgramArguments();
if (StringUtil.isEmpty(newProgramArguments))
{
newProgramArguments = "";
}
else
{
newProgramArguments += "\n";
}
newProgramArguments += programArguments;
compoundCommand.append(new SetCommand(domain, targletTask, SetupTargletsPackage.Literals.TARGLET_TASK__PROGRAM_ARGUMENTS,
newProgramArguments.replaceAll("[\n\r]+", "\n").trim()));
}
return dropCommand.canExecute();
}
private String getRepositoryListName(String defaultName)
{
// Compute a repository list name using this given one, the name of the *.target file, only as a default.
String lowerCaseDefaultName = defaultName.toLowerCase();
// Find the logical containing project catalog.
TargletTask targletTask = (TargletTask)owner;
for (Scope scope = targletTask.getScope(); scope != null; scope = scope.getParentScope())
{
if (scope instanceof ProjectCatalog)
{
// Look for the standard target platform variable.
for (Iterator<EObject> it = EcoreUtil.getAllProperContents(scope, false); it.hasNext();)
{
EObject child = it.next();
if (child instanceof VariableTask)
{
VariableTask variableTask = (VariableTask)child;
if ("eclipse.target.platform".equals(variableTask.getName()))
{
// Consider all the choices it provides.
String candidate = null;
for (VariableChoice variableChoice : variableTask.getChoices())
{
// If the name contains the variable choice's value, e.g., mars, use this choice.
String value = variableChoice.getValue();
if (lowerCaseDefaultName.contains(value.toLowerCase()))
{
return value;
}
// Determine the version number of this choice.
String label = variableChoice.getLabel();
if (label != null)
{
// If the name contains the version number of this choice, use this choice.
Matcher matcher = VERSION_PATTERN.matcher(label);
if (matcher.find() && defaultName.indexOf(matcher.group(1)) != -1)
{
return value;
}
}
// Use the first choice baring a better match.
if (candidate == null)
{
candidate = value;
}
}
// Use the first candidate, if a better match hasn't been found.
return candidate;
}
}
}
break;
}
}
// Failing all that, just use the default name.
return defaultName;
}
};
}
}
}
// We can't create a command at all.
return null;
}
});
// If we can create a command return it.
if (result != null)
{
return result;
}
}
catch (CoreException ex)
{
// Ignore.
}
}
}
}
}
// Just do the default thing.
return super.createCommand(object, domain, commandClass, commandParameter);
}
@SuppressWarnings("restriction")
@Override
protected Command createPrimaryDragAndDropCommand(EditingDomain domain, Object owner, float location, int operations, int operation, Collection<?> collection)
{
// Reflectively gather the paths associated with the EGit repository nodes.
final List<IPath> paths = new ArrayList<IPath>();
for (Object value : collection)
{
if ("org.eclipse.egit.ui.internal.repository.tree.RepositoryNode".equals(value.getClass().getName()))
{
paths.add((IPath)ReflectUtil.invokeMethod("getPath", value));
}
}
// If there are such paths, we can create a specialized drag and drop command.
if (collection.size() == paths.size())
{
return new TargletDragAndDropCommand(domain, owner, location, operations, operation, collection)
{
@Override
protected boolean prepareDropCopyOn()
{
dragCommand = IdentityCommand.INSTANCE;
dropCommand = new CompoundCommand(CompoundCommand.MERGE_COMMAND_ALL)
{
@Override
public void execute()
{
// Keep track of the requirements of any existing targlets.
final TargletTask targletTask = (TargletTask)owner;
List<Requirement> requirements = new ArrayList<Requirement>();
for (Targlet otherTarglet : targletTask.getTarglets())
{
for (Requirement requirement : otherTarglet.getRequirements())
{
requirements.add(requirement);
}
}
for (IPath path : paths)
{
// Always create a new targlet for each path.
Targlet targlet = TargletFactory.eINSTANCE.createTarglet();
// Use the path to create a new source locator.
// Later we hope to change the path to be a variable reference, but for analysis purposes, we need the current physical path.
// Then analyze the Git clone for IUs.
final SourceLocator sourceLocator = ResourcesFactory.eINSTANCE.createSourceLocator(path.toString(), true);
WorkspaceIUAnalyzer workspaceIUAnalyzer = new WorkspaceIUAnalyzer();
workspaceIUAnalyzer.analyze(sourceLocator, IUGenerator.DEFAULTS, new NullProgressMonitor());
Map<IInstallableUnit, WorkspaceIUInfo> workspaceIUInfos = workspaceIUAnalyzer.getWorkspaceIUInfos();
// Filter out any plain project IU for which there is another IU for the same physical project available.
final Set<IInstallableUnit> ius = workspaceIUInfos.keySet();
for (Iterator<Map.Entry<IInstallableUnit, WorkspaceIUInfo>> it = workspaceIUInfos.entrySet().iterator(); it.hasNext();)
{
Map.Entry<IInstallableUnit, WorkspaceIUInfo> entry = it.next();
String id = entry.getKey().getId();
if (id.endsWith(Requirement.PROJECT_SUFFIX))
{
WorkspaceIUInfo value = entry.getValue();
for (Iterator<Map.Entry<IInstallableUnit, WorkspaceIUInfo>> it2 = workspaceIUInfos.entrySet().iterator(); it2.hasNext();)
{
Map.Entry<IInstallableUnit, WorkspaceIUInfo> otherEntry = it2.next();
if (otherEntry != entry && otherEntry.getValue().equals(value))
{
it.remove();
break;
}
}
}
}
// Filter out any IU that's matched by a requirement of another IU, i.e., compute root IUs.
HashSet<IInstallableUnit> allIUs = new HashSet<IInstallableUnit>(ius);
final Set<Requirement> redundant = new HashSet<Requirement>();
IQueryable<IInstallableUnit> queryable = new CollectionResult<IInstallableUnit>(allIUs);
for (IInstallableUnit rootIU : allIUs)
{
for (IRequirement requirement : rootIU.getRequirements())
{
if (P2Util.isSimpleRequiredCapability(requirement))
{
// Any IU requirement that matches the name of an existing requirement makes that existing requirement redundant.
org.eclipse.equinox.internal.p2.metadata.IRequiredCapability requiredCapability = (org.eclipse.equinox.internal.p2.metadata.IRequiredCapability)requirement;
String namespace = requiredCapability.getNamespace();
if (IInstallableUnit.NAMESPACE_IU_ID.equals(namespace))
{
String name = requiredCapability.getName();
for (Requirement otherRequirement : requirements)
{
if (name.equals(otherRequirement.getName()))
{
redundant.add(otherRequirement);
}
}
}
// Filter out the non-root IU.
for (IInstallableUnit iu : P2Util.asIterable(queryable.query(QueryUtil.createMatchQuery(requirement.getMatches()), null)))
{
ius.remove(iu);
}
}
}
}
// Compute a nice name for the targlet and create requirements for all the root IUs.
targlet.setName(getTargletName("Default"));
EList<Requirement> targletRequirements = targlet.getRequirements();
for (IInstallableUnit iu : new TreeSet<IInstallableUnit>(ius))
{
Requirement requirement = P2Factory.eINSTANCE.createRequirement(iu.getId());
IMatchExpression<IInstallableUnit> filter = iu.getFilter();
if (filter != null)
{
requirement.setMatchExpression(filter);
}
targletRequirements.add(requirement);
}
// Determine, if possible a variable to use to refer to the path needed by the source locator,
// i.e., whenever possible the location variable of a Git clone task.
sourceLocator.setRootFolder(getSourceLocation(path));
targlet.getSourceLocators().add(sourceLocator);
// Add the new targlet and remove any redundant requirements from other targlets.
appendAndExecute(new AddCommand(domain, targletTask, SetupTargletsPackage.Literals.TARGLET_TASK__TARGLETS, targlet));
if (!redundant.isEmpty())
{
appendAndExecute(DeleteCommand.create(domain, redundant));
}
}
}
private String getSourceLocation(IPath path)
{
// Walk all the objects in the containing resource.
TargletTask targletTask = (TargletTask)owner;
Resource resource = targletTask.eResource();
if (resource != null)
{
String candidate = null;
for (Iterator<EObject> it = resource.getAllContents(); it.hasNext();)
{
// If it's a Git clone task.
EObject eObject = it.next();
EClass eClass = eObject.eClass();
if ("GitCloneTask".equals(eClass.getName()) && eObject instanceof SetupTask)
{
// If that task has an ID.
SetupTask setupTask = (SetupTask)eObject;
String id = setupTask.getID();
if (!StringUtil.isEmpty(id))
{
// Get the value of the remoteURI feature; it should have that feature.
EStructuralFeature eStructuralFeature = eClass.getEStructuralFeature("remoteURI");
if (eStructuralFeature != null)
{
// This is the variable reference for this task's location.
String result = "${" + id + ".location}";
if (candidate != null)
{
candidate = result;
}
String remoteURI = (String)eObject.eGet(eStructuralFeature);
try
{
// Convert it to a URI and try to determine the name of the git clone that will be produced from it.
URI uri = URI.createURI(remoteURI);
if (!uri.isHierarchical())
{
uri = URI.createURI(uri.opaquePart());
}
if ("git".equals(uri.fileExtension()))
{
uri = uri.trimFileExtension();
}
// If the path looks exactly like the location for this clone.
String baseName = URI.decode(uri.lastSegment());
if (path.toString().endsWith("/" + baseName))
{
// Use the variable for this task.
break;
}
}
catch (Throwable throwable)
{
// Ignore.
}
}
}
}
}
// If there is any satisfactory Git clone task, use the first one's variable reference.
if (candidate != null)
{
return candidate;
}
}
// If all else fails, simply use the path.
return path.toString();
}
@Override
protected boolean prepare()
{
return true;
}
};
return dropCommand.canExecute();
}
};
}
return super.createPrimaryDragAndDropCommand(domain, owner, location, operations, operation, collection);
}
/**
* Return the resource locator for this item provider's resources.
* <!-- begin-user-doc -->
* <!-- end-user-doc -->
* @generated
*/
@Override
public ResourceLocator getResourceLocator()
{
return SetupTargletsEditPlugin.INSTANCE;
}
/**
* @author Ed Merks
*/
private static class TargletDragAndDropCommand extends DragAndDropCommand
{
public TargletDragAndDropCommand(EditingDomain domain, Object owner, float location, int operations, int operation, Collection<?> collection)
{
super(domain, owner, location, operations, operation, collection, true);
}
protected String getTargletName(String defaultName)
{
// Compute the targlet name from the name of the containing project scope.
TargletTask targletTask = (TargletTask)owner;
for (Scope scope = targletTask.getScope(); scope != null; scope = scope.getParentScope())
{
if (scope instanceof Project)
{
String label = scope.getLabel();
if (StringUtil.isEmpty(label))
{
label = StringUtil.cap(scope.getName());
}
return label;
}
}
return defaultName;
}
}
/**
* @author Eike Stepper
*/
private static final class LocaleItemLabelProvider implements IItemLabelProvider
{
private final AdapterFactoryItemDelegator itemDelegator;
private Map<String, String> localeMap;
public LocaleItemLabelProvider(AdapterFactoryItemDelegator itemDelegator)
{
this.itemDelegator = itemDelegator;
}
public Object getImage(Object object)
{
return itemDelegator.getImage(object);
}
public String getText(Object object)
{
return getLocaleMap().get(object);
}
public Map<String, String> getLocaleMap()
{
if (localeMap == null)
{
localeMap = new HashMap<String, String>();
for (Locale locale : Locale.getAvailableLocales())
{
localeMap.put(locale.toString(), locale.toString() + " - " + locale.getDisplayName());
}
}
return localeMap;
}
}
}