Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'target_explorer/plugins/org.eclipse.tm.te.runtime.stepper/src/org/eclipse/tm/te/runtime/stepper/extensions/ContextStepGroup.java')
-rw-r--r--target_explorer/plugins/org.eclipse.tm.te.runtime.stepper/src/org/eclipse/tm/te/runtime/stepper/extensions/ContextStepGroup.java814
1 files changed, 814 insertions, 0 deletions
diff --git a/target_explorer/plugins/org.eclipse.tm.te.runtime.stepper/src/org/eclipse/tm/te/runtime/stepper/extensions/ContextStepGroup.java b/target_explorer/plugins/org.eclipse.tm.te.runtime.stepper/src/org/eclipse/tm/te/runtime/stepper/extensions/ContextStepGroup.java
new file mode 100644
index 000000000..626301c7d
--- /dev/null
+++ b/target_explorer/plugins/org.eclipse.tm.te.runtime.stepper/src/org/eclipse/tm/te/runtime/stepper/extensions/ContextStepGroup.java
@@ -0,0 +1,814 @@
+/*******************************************************************************
+ * Copyright (c) 2011 Wind River Systems, 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:
+ * Wind River Systems - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.tm.te.runtime.stepper.extensions;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.tm.te.runtime.interfaces.extensions.IExecutableExtension;
+import org.eclipse.tm.te.runtime.stepper.StepperManager;
+import org.eclipse.tm.te.runtime.stepper.activator.CoreBundleActivator;
+import org.eclipse.tm.te.runtime.stepper.interfaces.IContextStep;
+import org.eclipse.tm.te.runtime.stepper.interfaces.IContextStepGroup;
+import org.eclipse.tm.te.runtime.stepper.interfaces.IContextStepGroupable;
+import org.eclipse.tm.te.runtime.stepper.interfaces.IExtendedContextStep;
+import org.eclipse.tm.te.runtime.stepper.interfaces.tracing.ITraceIds;
+import org.eclipse.tm.te.runtime.stepper.nls.Messages;
+
+/**
+ * A default step group implementation.
+ */
+public class ContextStepGroup extends AbstractContextStepGroup {
+
+ private boolean locked;
+ private String baseOn;
+
+ private final List<ReferenceSubElement> references = new ArrayList<ReferenceSubElement>();
+
+ /**
+ * Step group reference sub element.
+ */
+ protected final static class ReferenceSubElement implements org.eclipse.core.runtime.IExecutableExtension {
+ private String id;
+ private String secondaryId;
+ private String insertBefore;
+ private String insertAfter;
+ private String overwrite;
+ private boolean removable;
+ private boolean hidden;
+ private boolean disable;
+ private boolean singleton;
+ private final List<String> dependencies = new ArrayList<String>();
+
+ /**
+ * Returns the id of the referenced step or step group.
+ *
+ * @return The id of the referenced step or step group.
+ */
+ public String getId() {
+ return id;
+ }
+
+ /**
+ * Returns the secondary id of the referenced step or step group.
+ *
+ * @return The secondary id or <code>null</code>.
+ */
+ public String getSecondaryId() {
+ return secondaryId;
+ }
+
+ /**
+ * Sets the secondary id of the referenced step or step group.
+ *
+ * @return The secondary id or <code>null</code>.
+ */
+ public void setSecondardId(String secondaryId) {
+ this.secondaryId = secondaryId;
+ }
+
+ /**
+ * Returns the id of the step or step group the referenced
+ * step or group shall be inserted before.
+ *
+ * @return The id or <code>null</code>.
+ */
+ public String getInsertBefore() {
+ return insertBefore;
+ }
+
+ /**
+ * Returns the id of the step or step group the referenced
+ * step or group shall be inserted after.
+ *
+ * @return The id or <code>null</code>.
+ */
+ public String getInsertAfter() {
+ return insertAfter;
+ }
+
+ /**
+ * Returns the id of the step or step group the referenced
+ * step or group do overwrite.
+ *
+ * @return The id or <code>null</code>.
+ */
+ public String getOverwrite() {
+ return overwrite;
+ }
+
+ /**
+ * Returns if or if not the referenced step or step group
+ * can be removed by the user from the group.
+ *
+ * @return <code>True</code> if removable, <code>false</code> otherwise.
+ */
+ public boolean isRemovable() {
+ return removable;
+ }
+
+ /**
+ * Returns if or if not the referenced step or step group
+ * is hidden.
+ *
+ * @return <code>True</code> if hidden, <code>false</code> otherwise.
+ */
+ public boolean isHidden() {
+ return hidden;
+ }
+
+ /**
+ * Returns if or if not to disable the referenced step or step group.
+ *
+ * @return <code>True</code> if to disable, <code>false</code> otherwise.
+ */
+ public boolean isDisable() {
+ return disable;
+ }
+
+ /**
+ * Returns if or if not the referenced step or step group is a singleton.
+ *
+ * @return <code>True</code> if singleton, <code>false</code> otherwise.
+ */
+ public boolean isSingleton() {
+ return singleton;
+ }
+
+ /**
+ * Returns the list of dependencies.
+ * <p>
+ * The step or step group id might be fully qualified using the form
+ * <code>&quot;primaryId##secondaryId</code>. The <code>secondaryId</code> is optional.
+ *
+ * @return The list of dependencies or an empty list.
+ */
+ public String[] getDependencies() {
+ return dependencies.toArray(new String[dependencies.size()]);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
+ */
+ @Override
+ public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
+ if (config == null) {
+ return;
+ }
+
+ String value = config.getAttribute("id"); //$NON-NLS-1$
+ if (value != null && value.trim().length() > 0) {
+ this.id = value.trim();
+ }
+
+ value = config.getAttribute("secondaryId"); //$NON-NLS-1$
+ setSecondardId(value != null && value.trim().length() > 0 ? value.trim() : null);
+
+ value = config.getAttribute("insertBefore"); //$NON-NLS-1$
+ if (value != null && value.trim().length() > 0) {
+ this.insertBefore = value.trim();
+ }
+
+ value = config.getAttribute("insertAfter"); //$NON-NLS-1$
+ if (value != null && value.trim().length() > 0) {
+ this.insertAfter = value.trim();
+ }
+
+ value = config.getAttribute("overwrite"); //$NON-NLS-1$
+ if (value != null && value.trim().length() > 0) {
+ this.overwrite = value.trim();
+ }
+
+ value = config.getAttribute("removable"); //$NON-NLS-1$
+ if (value != null && value.trim().length() > 0) {
+ this.removable = Boolean.parseBoolean(value.trim());
+ }
+
+ value = config.getAttribute("hidden"); //$NON-NLS-1$
+ if (value != null && value.trim().length() > 0) {
+ this.hidden = Boolean.parseBoolean(value.trim());
+ }
+
+ value = config.getAttribute("disable"); //$NON-NLS-1$
+ if (value != null && value.trim().length() > 0) {
+ this.disable = Boolean.parseBoolean(value.trim());
+ }
+
+ value = config.getAttribute("singleton"); //$NON-NLS-1$
+ if (value != null && value.trim().length() > 0) {
+ this.singleton = Boolean.parseBoolean(value.trim());
+ }
+
+ // Read in the list of dependencies if specified.
+ dependencies.clear();
+ IConfigurationElement[] requires = config.getChildren("requires"); //$NON-NLS-1$
+ for (IConfigurationElement require : requires) {
+ value = require.getAttribute("id"); //$NON-NLS-1$
+ if (value == null || value.trim().length() == 0) {
+ throw new CoreException(new Status(IStatus.ERROR,
+ CoreBundleActivator.getUniqueIdentifier(),
+ 0,
+ NLS.bind(Messages.AbstractContextStep_error_missingRequiredAttribute,
+ "dependency id (requires)", //$NON-NLS-1$
+ config.getName()),
+ null));
+ }
+ if (!dependencies.contains(value.trim())) {
+ dependencies.add(value.trim());
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ @Override
+ public boolean equals(Object obj) {
+ if (getId() != null && obj instanceof ReferenceSubElement) {
+ boolean secondaryIdEquals = false;
+ if (getSecondaryId() == null) {
+ secondaryIdEquals = ((ReferenceSubElement)obj).getSecondaryId() == null;
+ }
+ else {
+ secondaryIdEquals = getSecondaryId().equals(((ReferenceSubElement)obj).getSecondaryId());
+ }
+
+ return getId().equals(((ReferenceSubElement)obj).getId()) && secondaryIdEquals;
+ }
+ return super.equals(obj);
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#hashCode()
+ */
+ @Override
+ public int hashCode() {
+ return getId() != null ? getId().hashCode() + (getSecondaryId() != null ? getSecondaryId().hashCode() : 0) : super.hashCode();
+ }
+
+ /* (non-Javadoc)
+ * @see java.lang.Object#toString()
+ */
+ @Override
+ public String toString() {
+ StringBuffer buffer = new StringBuffer(getClass().getSimpleName());
+ buffer.append(": "); //$NON-NLS-1$
+ buffer.append("id = " + getId()); //$NON-NLS-1$
+ buffer.append(", secondaryId = " + getSecondaryId()); //$NON-NLS-1$
+ buffer.append(", insertBefore = " + getInsertBefore()); //$NON-NLS-1$
+ buffer.append(", insertAfter = " + getInsertAfter()); //$NON-NLS-1$
+ buffer.append(", overwrite = " + getOverwrite()); //$NON-NLS-1$
+ buffer.append(", removable = " + isRemovable()); //$NON-NLS-1$
+ buffer.append(", hidden = " + isHidden()); //$NON-NLS-1$
+ buffer.append(", disable = " + isDisable()); //$NON-NLS-1$
+ buffer.append(", singleton = " + isSingleton()); //$NON-NLS-1$
+ return buffer.toString();
+ }
+ }
+
+ /**
+ * Constructor.
+ */
+ public ContextStepGroup() {
+ super();
+ locked = false;
+ baseOn = null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tm.te.runtime.stepper.AbstractContextStepGroup#isLocked()
+ */
+ @Override
+ public boolean isLocked() {
+ return locked;
+ }
+
+ /**
+ * Returns the id of the step group this step group is
+ * initially based on.
+ *
+ * @return The id or <code>null</code>.
+ */
+ protected String getBaseOn() {
+ return baseOn;
+ }
+
+ /**
+ * Returns the references.
+ */
+ protected List<ReferenceSubElement> getReferences() {
+ return references;
+ }
+
+ /**
+ * Check for duplicates of the referenced step or step group. The check
+ * will fail if multiple occurrence of a step or step group are found and
+ * the step or step group is supposed to be a singleton.
+ *
+ * @param steps The list of steps. Must not be <code>null</code>.
+ * @param reference The reference. Must not be <code>null</code>.
+ * @param type The type id. Must not be <code>null</code>.
+ * @param mode The sub type id. Must not be <code>null</code>.
+ *
+ * @throws CoreException If multiple occurrences of singleton references are found.
+ */
+ protected void checkForDuplicates(List<IContextStepGroupable> steps, ReferenceSubElement reference, String type, String mode) throws CoreException {
+ assert steps != null && reference != null;
+
+ // If the reference overwrites another reference, it is not a duplicate
+ String overwrite = reference.getOverwrite();
+ if (overwrite != null && overwrite.length() > 0) {
+ return;
+ }
+
+ boolean checkFailed = false;
+
+ for (IContextStepGroupable step : steps) {
+ if (step.getExtension().getId().equals(reference.getId())) {
+ // We've found an existing groupable with the reference id.
+ // If either the groupable, the reference or the extension is
+ // marked singleton, than this is an failure.
+ checkFailed = step.isSingleton() || reference.isSingleton()
+ || (step.getExtension() instanceof IExtendedContextStep
+ && ((IExtendedContextStep)step.getExtension()).isSingleton());
+ if (checkFailed) {
+ break;
+ }
+ }
+ }
+
+ if (checkFailed) {
+ throw new CoreException(new Status(IStatus.ERROR,
+ CoreBundleActivator.getUniqueIdentifier(),
+ MessageFormat.format(Messages.ContextStepGroup_error_multipleSingletonOccurrences,
+ NLS.bind(Messages.ContextStepGroup_error_stepGroup, getLabel()),
+ NLS.bind(Messages.ContextStepGroup_error_referencedStepOrGroup, reference.getId()),
+ NLS.bind(Messages.ContextStepGroup_error_typeAndMode, type, mode))
+ ));
+ }
+ }
+
+ /**
+ * Replace all references to a given step or step group with another one.
+ *
+ * @param steps The list of steps. Must not be <code>null</code>.
+ * @param oldId The id of the step or step group to replace. Must not be <code>null</code>.
+ * @param replacement The replacement. Must not be <code>null</code>.
+ * @param reference The reference sub element. Must not be <code>null</code>.
+ *
+ * @return The list of affected groupable's or an empty list.
+ */
+ protected List<IContextStepGroupable> onOverwrite(List<IContextStepGroupable> steps, String oldId, IExecutableExtension replacement, ReferenceSubElement reference) {
+ assert steps != null && oldId != null && replacement != null && reference != null;
+
+ List<IContextStepGroupable> affected = new ArrayList<IContextStepGroupable>();
+
+ // Isolate primary and secondary id
+ String primaryId = oldId;
+ String secondaryId = null;
+
+ String[] splitted = oldId.split("##", 2); //$NON-NLS-1$
+ if (splitted.length == 2) {
+ primaryId = splitted[0];
+ secondaryId = splitted[1];
+ }
+
+ for (IContextStepGroupable step : steps) {
+ // A step is clearly affected if the primary id and the secondary
+ // id (if any) matches the overwritten id
+ if (step.getExtension().getId().equals(primaryId)
+ && (secondaryId == null || secondaryId.equals(step.getSecondaryId()))) {
+ if (step instanceof ContextStepGroupable) {
+ ContextStepGroupable groupable = ((ContextStepGroupable)step);
+ // Update the grouped extension
+ groupable.setExtension(replacement);
+ // Update the groupable secondary id
+ groupable.setSecondaryId(reference.getSecondaryId());
+ // Add the groupable to the list of affected steps
+ affected.add(step);
+ }
+ }
+
+ // A step is affected as well if the step depends on the overwritten step
+ // In this case we have to update the dependencies.
+ List<String> dependencies = new ArrayList<String>(Arrays.asList(step.getDependencies()));
+ if (dependencies.contains(oldId)) {
+ String fullId = replacement.getId() + (reference.getSecondaryId() != null ? "##" + reference.getSecondaryId() : ""); //$NON-NLS-1$ //$NON-NLS-2$
+ // We have to replace the dependency at the exact position within the list
+ dependencies.set(dependencies.indexOf(oldId), fullId);
+ if (step instanceof ContextStepGroupable) {
+ ((ContextStepGroupable)step).setDependencies(dependencies.toArray(new String[dependencies.size()]));
+ }
+ }
+ }
+
+ return affected;
+ }
+
+ /**
+ * Insert the step before the specified step or step group. If no step or
+ * step group with the given id exist, the step is added to the end.
+ *
+ * @param steps The list of steps. Must not be <code>null</code>.
+ * @param id The id of the step or step group where to insert the new step before. Must not be <code>null</code>.
+ * @param newStep The step to add. Must not be <code>null</code>.
+ * @param reference The reference sub element. Must not be <code>null</code>.
+ *
+ * @return The list of affected groupable's or an empty list.
+ */
+ protected List<IContextStepGroupable> onInsertBefore(List<IContextStepGroupable> steps, String id, IExecutableExtension newStep, ReferenceSubElement reference) {
+ assert steps != null && id != null && newStep != null && reference != null;
+
+ List<IContextStepGroupable> affected = new ArrayList<IContextStepGroupable>();
+
+ // Isolate primary and secondary id
+ String primaryId = id;
+ String secondaryId = null;
+
+ String[] splitted = id.split("##", 2); //$NON-NLS-1$
+ if (splitted.length == 2) {
+ primaryId = splitted[0];
+ secondaryId = splitted[1];
+ }
+
+ // Always loop over all steps in case the anchor step is available
+ // multiple times. In such case, the new step is inserted at all
+ // occurrences.
+ for (int i = 0; i < steps.size(); i++) {
+ IContextStepGroupable step = steps.get(i);
+ if (!step.getExtension().getId().equals(primaryId)) {
+ continue;
+ }
+ if (secondaryId != null && !secondaryId.equals(step.getSecondaryId())) {
+ continue;
+ }
+
+ // Create a new groupable object for inserting
+ IContextStepGroupable groupable = new ContextStepGroupable(newStep, reference.getSecondaryId());
+ // Insert the new step at the current position
+ steps.add(i, groupable);
+ // And increase the counter --> Otherwise we would see the
+ // same step we want to insert before again!
+ i++;
+ // Add the new groupable to the list of affected steps
+ affected.add(groupable);
+ }
+
+ // If the step could not be added, add to the end of the list
+ if (affected.isEmpty()) {
+ IContextStepGroupable groupable = new ContextStepGroupable(newStep, reference.getSecondaryId());
+ steps.add(groupable);
+ }
+
+ return affected;
+ }
+
+ /**
+ * Insert the step after the specified step or step group. If no step or
+ * step group with the given id exist, the step is added to the end.
+ *
+ * @param steps The list of steps. Must not be <code>null</code>.
+ * @param id The id of the step or step group where to insert the new step after. Must not be <code>null</code>.
+ * @param newStep The step to add. Must not be <code>null</code>.
+ * @param reference The reference sub element. Must not be <code>null</code>.
+ *
+ * @return The list of affected groupable's or an empty list.
+ */
+ protected List<IContextStepGroupable> onInsertAfter(List<IContextStepGroupable> steps, String id, IExecutableExtension newStep, ReferenceSubElement reference) {
+ assert steps != null && id != null && newStep != null && reference != null;
+
+ List<IContextStepGroupable> affected = new ArrayList<IContextStepGroupable>();
+
+ // Isolate primary and secondary id
+ String primaryId = id;
+ String secondaryId = null;
+
+ String[] splitted = id.split("##", 2); //$NON-NLS-1$
+ if (splitted.length == 2) {
+ primaryId = splitted[0];
+ secondaryId = splitted[1];
+ }
+
+ // Always loop over all steps in case the anchor step is available
+ // multiple times. In such case, the new step is inserted at all
+ // occurrences.
+ for (int i = 0; i < steps.size(); i++) {
+ IContextStepGroupable step = steps.get(i);
+ if (!step.getExtension().getId().equals(primaryId)) {
+ continue;
+ }
+ if (secondaryId != null && !secondaryId.equals(step.getSecondaryId())) {
+ continue;
+ }
+
+ // Create a new groupable object for inserting
+ IContextStepGroupable groupable = new ContextStepGroupable(newStep, reference.getSecondaryId());
+ // Insert the new groupable after the current step or at the end (if i + 1 == steps.size())
+ steps.add(i + 1, groupable);
+ // Add the new groupable to the list of affected steps
+ affected.add(groupable);
+ }
+
+ // If the step could not be added, add to the end of the list
+ if (affected.isEmpty()) {
+ IContextStepGroupable groupable = new ContextStepGroupable(newStep, reference.getSecondaryId());
+ steps.add(groupable);
+ }
+
+ return affected;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tm.te.runtime.stepper.interfaces.IContextStepGroup#getSteps(java.lang.String, java.lang.String)
+ */
+ @Override
+ public IContextStepGroupable[] getSteps(String type, String mode) throws CoreException {
+ assert type != null && mode != null;
+
+ // The list of resolved steps for the specified type and mode
+ List<IContextStepGroupable> steps = new ArrayList<IContextStepGroupable>();
+
+ // If this step group is based on another step group, we have to get the resolved
+ // steps from there first.
+ if (getBaseOn() != null) {
+ IContextStepGroup baseStepGroup = getStepGroup(getBaseOn());
+ // If the base step group cannot be found, that's an error. We cannot continue
+ // without the base group.
+ if (baseStepGroup == null) {
+ throw new CoreException(new Status(IStatus.ERROR,
+ CoreBundleActivator.getUniqueIdentifier(),
+ MessageFormat.format(Messages.ContextStepGroup_error_missingBaseStepGroup,
+ NLS.bind(Messages.ContextStepGroup_error_stepGroup, getLabel()),
+ NLS.bind(Messages.ContextStepGroup_error_referencedBaseGroup, getBaseOn()),
+ NLS.bind(Messages.ContextStepGroup_error_typeAndMode, type, mode))
+ ));
+ }
+
+ // Add all the steps from the base step group now to the list
+ steps.addAll(Arrays.asList(baseStepGroup.getSteps(type, mode)));
+ }
+
+ // Now process the references and modify the steps list accordingly
+ for (ReferenceSubElement reference : getReferences()) {
+ // Get the step or step group for the referenced id. Try the steps first.
+ IExecutableExtension candidate = getStep(reference.getId());
+ if (candidate == null) {
+ candidate = getStepGroup(reference.getId());
+ }
+
+ // If the candidate is null here, that's an error as a referenced step is missing.
+ if (candidate == null) {
+ throw new CoreException(new Status(IStatus.ERROR,
+ CoreBundleActivator.getUniqueIdentifier(),
+ MessageFormat.format(Messages.ContextStepGroup_error_missingReferencedStep,
+ NLS.bind(Messages.ContextStepGroup_error_stepGroup, getLabel()),
+ NLS.bind(Messages.ContextStepGroup_error_referencedStepOrGroup, reference.getId()),
+ NLS.bind(Messages.ContextStepGroup_error_typeAndMode, type, mode))
+ ));
+ }
+
+ // Check if the step is valid for the current launch configuration type and mode.
+ if (candidate instanceof IContextStep) {
+ boolean valid = isValidStep(candidate.getId(), type, mode);
+
+ if (!valid) {
+ CoreBundleActivator.getTraceHandler().trace(
+ "StepGroup#getSteps: SKIPPED step = '" + candidate.getLabel() + "'." //$NON-NLS-1$ //$NON-NLS-2$
+ + " Not valid for type id '" + type + "'" //$NON-NLS-1$ //$NON-NLS-2$
+ + " and mode '" + mode + "'", //$NON-NLS-1$ //$NON-NLS-2$
+ 0, ITraceIds.TRACE_STEPPING, IStatus.WARNING, this);
+ continue;
+ }
+ }
+
+ // Check for duplicates of singleton references.
+ checkForDuplicates(steps, reference, type, mode);
+
+ // Check for the steps own dependencies to be valid for the current type id and mode
+ if (candidate instanceof IContextStep) {
+ checkForDependenciesValid((IContextStep) candidate, type, mode);
+ }
+
+ // Will contain the list of affected groupables from the whole list
+ List<IContextStepGroupable> affectedGroupables = new ArrayList<IContextStepGroupable>();
+
+ // Check first for overwriting groupables
+ String overwrite = reference.getOverwrite();
+ if (overwrite != null && overwrite.length() > 0) {
+ affectedGroupables.addAll(onOverwrite(steps, overwrite, candidate, reference));
+ } else {
+ // overwrite is not set -> process insertBefore or insertAfter
+ String insertBefore = reference.getInsertBefore();
+ String insertAfter = reference.getInsertAfter();
+
+ // If neither one is specified, the step or step group will be to the end of the list
+ if ((insertBefore == null || insertBefore.length() == 0)
+ && (insertAfter == null || insertAfter.length() == 0)) {
+ IContextStepGroupable groupable = new ContextStepGroupable(candidate, reference.getSecondaryId());
+ steps.add(groupable);
+ affectedGroupables.add(groupable);
+ } else {
+ // insertBefore comes first
+ if (insertBefore != null && insertBefore.length() > 0) {
+ affectedGroupables.addAll(onInsertBefore(steps, insertBefore, candidate, reference));
+ } else {
+ affectedGroupables.addAll(onInsertAfter(steps, insertAfter, candidate, reference));
+ }
+ }
+ }
+
+ // Process the groupable attributes on all affected groupables
+ for (IContextStepGroupable step : affectedGroupables) {
+ if (!(step instanceof ContextStepGroupable)) {
+ continue;
+ }
+
+ ContextStepGroupable groupable = (ContextStepGroupable)step;
+ groupable.setDependencies(reference.getDependencies());
+
+ if (!reference.isRemovable() && groupable.isRemovable()) {
+ groupable.setRemovable(reference.isRemovable());
+ }
+ if (reference.isHidden() && !groupable.isHidden()) {
+ groupable.setHidden(reference.isHidden());
+ }
+ if (reference.isDisable() && !groupable.isDisabled()) {
+ groupable.setDisabled(reference.isDisable());
+ }
+ if (reference.isSingleton() && !groupable.isSingleton()) {
+ groupable.setSingleton(reference.isSingleton());
+ }
+ }
+ }
+
+ return !steps.isEmpty() ? steps.toArray(new IContextStepGroupable[steps.size()]) : NO_STEPS;
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tm.te.runtime.extensions.ExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
+ */
+ @Override
+ public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
+ references.clear();
+ super.setInitializationData(config, propertyName, data);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.tm.te.runtime.stepper.extensions.AbstractContextStepGroup#doSetInitializationData(org.eclipse.core.runtime.IConfigurationElement, java.lang.String, java.lang.Object)
+ */
+ @Override
+ public void doSetInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException {
+ super.doSetInitializationData(config, propertyName, data);
+
+ if (!locked) {
+ String lockedAttribute = config.getAttribute("locked"); //$NON-NLS-1$
+ if (lockedAttribute != null) {
+ this.locked = Boolean.parseBoolean(lockedAttribute);
+ }
+ }
+
+ if (baseOn == null || baseOn.trim().length() == 0) {
+ String baseOnAttribute = config.getAttribute("baseOn"); //$NON-NLS-1$
+ if (baseOnAttribute != null && baseOnAttribute.trim().length() > 0) {
+ this.baseOn = baseOnAttribute.trim();
+ }
+ }
+
+ Map<String, Integer> occurrences = new HashMap<String, Integer>();
+ IConfigurationElement[] childElements = config.getChildren("references"); //$NON-NLS-1$
+ for (IConfigurationElement childElement : childElements) {
+ IConfigurationElement[] references = childElement.getChildren("reference"); //$NON-NLS-1$
+ for (IConfigurationElement reference : references) {
+ ReferenceSubElement candidate = new ReferenceSubElement();
+ candidate.setInitializationData(reference, reference.getName(), null);
+ // If multiple references to the same step or step group exist, check
+ // for the secondaryId
+ if (occurrences.containsKey(candidate.getId())) {
+ // Occurrences are counted up always
+ int number = occurrences.get(candidate.getId()).intValue() + 1;
+ occurrences.put(candidate.getId(), Integer.valueOf(number));
+
+ if (candidate.getSecondaryId() == null) {
+ // secondaryId not explicitly set -> auto set
+ candidate.setSecondardId(Integer.toString(number));
+ }
+ } else {
+ // remember the occurrence of the reference
+ occurrences.put(candidate.getId(), Integer.valueOf(1));
+ }
+
+ // References are not sorted out here. That's the task of the resolver.
+ this.references.add(candidate);
+ }
+ }
+ }
+
+
+ /**
+ * Checks is all dependencies of the given step are available
+ * and valid for the given type id and mode.
+ *
+ * @param step The step. Must not be <code>null</code>.
+ * @param type The type id. Must not be <code>null</code>.
+ * @param mode The mode. Must not be <code>null</code>.
+ *
+ * @throws CoreException If a required step or step group is not available or not valid.
+ */
+ protected void checkForDependenciesValid(IContextStep step, String type, String mode) throws CoreException {
+ assert step != null && type != null && mode != null;
+
+ String[] dependencies = step.getDependencies();
+ for (String dependency : dependencies) {
+ // Get the step or step group. Try the steps first.
+ IExecutableExtension candidate = getStep(dependency);
+ if (candidate == null) {
+ candidate = getStepGroup(dependency);
+ }
+
+ // If the candidate is null here, that's an error as a required step or step group is missing.
+ if (candidate == null) {
+ throw new CoreException(new Status(IStatus.ERROR,
+ CoreBundleActivator.getUniqueIdentifier(),
+ MessageFormat.format(Messages.ContextStepGroup_error_missingRequiredStep,
+ NLS.bind(Messages.ContextStepGroup_error_step, step.getLabel()),
+ NLS.bind(Messages.ContextStepGroup_error_requiredStepOrGroup, dependency),
+ NLS.bind(Messages.ContextStepGroup_error_typeAndMode, type, mode))
+ ));
+ }
+
+ // If the candidate a step, validate the step
+ if (candidate instanceof IContextStep) {
+ IContextStep candidateStep = (IContextStep)candidate;
+ boolean valid = isValidStep(candidateStep.getId(), type, mode);
+ if (!valid) {
+ throw new CoreException(new Status(IStatus.ERROR,
+ CoreBundleActivator.getUniqueIdentifier(),
+ MessageFormat.format(Messages.ContextStepGroup_error_invalidRequiredStep,
+ NLS.bind(Messages.ContextStepGroup_error_step, step.getLabel()),
+ NLS.bind(Messages.ContextStepGroup_error_requiredStep, dependency),
+ NLS.bind(Messages.ContextStepGroup_error_typeAndMode, type, mode))
+ ));
+ }
+
+ // Step is valid -> recursively check required steps.
+ checkForDependenciesValid(candidateStep, type, mode);
+ }
+ }
+ }
+
+ /**
+ * Convenience method returning a unique instance of the step
+ * identified by the given id.
+ *
+ * @param id The step id. Must not be <code>null</code>.
+ * @return The step instance or <code>null</code>.
+ */
+ protected IContextStep getStep(String id) {
+ Assert.isNotNull(id);
+ return StepperManager.getInstance().getStepExtManager().getStep(id, true);
+ }
+
+ /**
+ * Convenience method returning a unique instance of the step
+ * group identified by the given id.
+ *
+ * @param id The step id. Must not be <code>null</code>.
+ * @return The step group instance or <code>null</code>.
+ */
+ protected IContextStepGroup getStepGroup(String id) {
+ Assert.isNotNull(id);
+ return StepperManager.getInstance().getStepGroupExtManager().getStepGroup(id, true);
+ }
+
+ /**
+ * Returns if or if not the step identified by the given id is valid.
+ * <p>
+ * <b>Note:</b> The default implementation returns always <code>true</code>.
+ *
+ * @param id The step id. Must not be <code>null</code>.
+ * @param type The type id. Must not be <code>null</code>.
+ * @param mode The mode. Must not be <code>null</code>.
+ *
+ * @return <code>True</code> if the step is valid, <code>false</code> otherwise.
+ */
+ protected boolean isValidStep(String id, String type, String mode) {
+ return true;
+ }
+}

Back to the top