blob: 0c8267ae5d9fb9052a03c6d4b2848ca02e1b3beb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2017 SSI Schaefer IT Solutions GmbH 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:
* SSI Schaefer IT Solutions GmbH
*******************************************************************************/
package org.eclipse.tea.library.build.chain;
import java.util.Set;
import java.util.TreeSet;
import org.eclipse.core.runtime.Assert;
import org.eclipse.tea.library.build.services.TeaElementFailurePolicy;
import org.eclipse.tea.library.build.services.TeaElementFailurePolicy.FailurePolicy;
/**
* Base class for a single build element of a {@link TeaBuildChain}.
*/
@TeaElementFailurePolicy(FailurePolicy.USE_THRESHOLD)
public abstract class TeaBuildElement implements Comparable<TeaBuildElement> {
/** wire to this element, currently can be the same for all callers */
private final TeaDependencyWire selfWire = new TeaDependencyWire(this);
/** all dependencies to other elements */
private final Set<TeaDependencyWire> dependencyWires = new TreeSet<>();
/** build order; a negative value if not yet calculated */
private int buildOrder = -1;
/**
* Returns the internal name of this element. This name must be unique
* throughout the system!
*/
public abstract String getName();
/**
* Returns the build order value for this element.
*
* @returns the build order; the builds must run in ascending order, cycles
* are forbidden
*/
protected final int getBuildOrder() {
if (buildOrder >= 0) {
return buildOrder;
}
if (buildOrder == -2) {
// already in calculation!
throw new IllegalStateException("circular dependency detected in " + this);
}
// set to -2 to detect circular dependencies
buildOrder = -2;
// calculate the build order
buildOrder = calcBuildOrder(1);
return buildOrder;
}
/**
* Calculates the build order value for this element.
*
* @param minValue
* minimal order value
* @returns the build order (>=minValue)
*/
protected int calcBuildOrder(int minValue) {
int result = minValue;
for (TeaDependencyWire wire : dependencyWires) {
TeaBuildElement target = wire.getTarget();
if (target instanceof TeaUnhandledElement) {
throw new RuntimeException("depenendecy from " + getName() + " to " + target.getName()
+ " not possible. Target unhandled.");
}
int depOrder = target.getBuildOrder();
if (depOrder >= result) {
result = depOrder + 1;
}
}
return result;
}
/**
* Add a dependency from this {@link TeaBuildElement} to another one.
*
* @param wire
* the wire to the opposite {@link TeaBuildElement}.
*/
public void addDependencyWire(TeaDependencyWire wire) {
Assert.isTrue(buildOrder == -1, "may add dependencies only before order calculation");
dependencyWires.add(wire);
}
/**
* @return all {@link TeaDependencyWire}s to other {@link TeaBuildElement}s.
*/
public Set<TeaDependencyWire> getDependencyWires() {
return dependencyWires;
}
/**
* @return a {@link TeaDependencyWire} to this {@link TeaBuildElement} that
* can be added to another {@link TeaBuildElement}.
*/
public TeaDependencyWire createWire() {
// once more contextual information is required on dependency wires, we
// can resort to creating wires on the fly here.
return selfWire;
}
@Override
public String toString() {
return getClass().getSimpleName() + ", name=" + getName();
}
@Override
public int compareTo(TeaBuildElement o) {
return getName().compareTo(o.getName());
}
}