Skip to content

Commit

Permalink
improve the dependency declaration of commands
Browse files Browse the repository at this point in the history
  • Loading branch information
rakow committed Dec 18, 2024
1 parent 1d9af0f commit b69989f
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,10 +75,12 @@ public void run(Path input) {
for (Map.Entry<Class<? extends MATSimAppCommand>, String[]> e : args.entrySet()) {
Class<? extends MATSimAppCommand> clazz = e.getKey();
graph.addVertex(clazz);
Class<? extends MATSimAppCommand>[] depends = ApplicationUtils.getSpec(clazz).dependsOn();
for (Class<? extends MATSimAppCommand> d : depends) {
graph.addVertex(d);
graph.addEdge(d, clazz);
Dependency[] depends = ApplicationUtils.getSpec(clazz).dependsOn();
for (Dependency d : depends) {
if (d.required()) {
graph.addVertex(d.value());
graph.addEdge(d.value(), clazz);
}
}
if (depends.length == 0)
start.add(clazz);
Expand Down Expand Up @@ -149,11 +151,11 @@ private String[] createArgs(Class<? extends MATSimAppCommand> command, String[]
if (present)
continue;

for (Class<? extends MATSimAppCommand> depend : spec.dependsOn()) {
CommandSpec dependency = ApplicationUtils.getSpec(depend);
for (Dependency depend : spec.dependsOn()) {
CommandSpec dependency = ApplicationUtils.getSpec(depend.value());
if (ArrayUtils.contains(dependency.produces(), require)) {

String path = getPath(depend, require);
String path = getPath(depend.value(), require);

args.add(arg);
args.add(path);
Expand Down Expand Up @@ -308,9 +310,9 @@ public void add(Class<? extends MATSimAppCommand> command, String... args) {
CommandSpec spec = ApplicationUtils.getSpec(command);

// Add dependent classes
for (Class<? extends MATSimAppCommand> depends : spec.dependsOn()) {
if (!this.args.containsKey(depends))
add(depends);
for (Dependency depends : spec.dependsOn()) {
if (!this.args.containsKey(depends.value()))
add(depends.value());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,9 @@
String[] produces() default {};

/**
* Other commands that produce the input needed by this command.
* Other commands that produce input needed by this command.
*/
Class<? extends MATSimAppCommand>[] dependsOn() default {};
// Dependency[] dependsOn() default {};
Dependency[] dependsOn() default {};

/**
* Group name / identifier. Will use the package name if this is not changed here.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
package org.matsim.application;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* Defines a dependency to be used in a {@link CommandSpec}.
* This annotation is not used directly on other classes.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE_USE)
public @interface Dependency {

/**
* Analysis command required by this command.
*/
Class<? extends MATSimAppCommand> value();

/**
* List of file names that are used as input for this class.
*/
String[] files() default {};

/**
* Whether this dependency is required.
*/
boolean required() default false;

}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import org.matsim.api.core.v01.Scenario;
import org.matsim.application.ApplicationUtils;
import org.matsim.application.CommandSpec;
import org.matsim.application.Dependency;
import org.matsim.application.MATSimAppCommand;
import org.matsim.application.analysis.emissions.AirPollutionAnalysis;
import org.matsim.application.analysis.population.TripAnalysis;
import org.matsim.application.options.InputOptions;
import org.matsim.application.options.OutputOptions;
Expand All @@ -23,12 +25,10 @@
name = "impact"
)
@CommandSpec(requireRunDirectory = true,
requires = {"trip_stats.csv"},
dependsOn = {TripAnalysis.class},
// dependsOn = {
// @Dependency(value = TripAnalysis.class, files = "trip_stats.csv")
// // @Dependency(value = AirPollutionAnalysis.class, files = "...")
// },
dependsOn = {
@Dependency(value = TripAnalysis.class, files = "trip_stats.csv"),
@Dependency(value = AirPollutionAnalysis.class, files = "...")
},
produces = {
"data.csv",
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,18 @@
import org.matsim.api.core.v01.network.Network;
import org.matsim.api.core.v01.population.Population;
import org.matsim.application.CommandSpec;
import org.matsim.application.Dependency;
import org.matsim.application.MATSimAppCommand;
import org.matsim.core.network.NetworkUtils;
import org.matsim.core.population.PopulationUtils;
import picocli.CommandLine;

import javax.annotation.Nullable;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicBoolean;

/**
Expand Down Expand Up @@ -106,6 +110,28 @@ public String getPath(String name) {
return inputs.get(name);
}

/**
* Return the path to a file provided by command defined as dependency.
* @param clazz dependency
* @param name file name
*
* @return can be null if not provided and the dependency is not required.
*/
@Nullable
public String getPath(Class<? extends MATSimAppCommand> clazz, String name) {
Optional<Dependency> first = Arrays.stream(spec.dependsOn())
.filter(d -> d.value().equals(clazz))
.findFirst();

if (first.isEmpty())
throw new IllegalArgumentException(String.format("Dependency to '%s' is not defined in @CommandSpec.", clazz));

if (first.get().required() && !inputs.containsKey(name))
throw new IllegalArgumentException(String.format("Path to '%s' is required but not provided.", name));

return inputs.get(name);
}

public Network getNetwork() {
if (!spec.requireNetwork())
throw new IllegalArgumentException("Network can not be accessed unless, requireNetwork=true.");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.matsim.application.analysis;

import org.matsim.application.CommandSpec;
import org.matsim.application.Dependency;
import org.matsim.application.MATSimAppCommand;
import org.matsim.application.options.InputOptions;
import org.matsim.application.options.OutputOptions;
Expand All @@ -9,7 +10,10 @@
import java.nio.file.Files;
import java.nio.file.Path;

@CommandSpec(requires = {"out.xml"}, produces = "processed.csv", dependsOn = {TestAnalysis.class})
@CommandSpec(
produces = "processed.csv",
dependsOn = {@Dependency(value = TestAnalysis.class, files = {"out.xml"}, required = true)}
)
public class TestDependentAnalysis implements MATSimAppCommand {

@CommandLine.Mixin
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
package org.matsim.application.analysis;

import org.matsim.application.CommandSpec;
import org.matsim.application.Dependency;
import org.matsim.application.MATSimAppCommand;
import org.matsim.application.options.InputOptions;
import org.matsim.application.options.OutputOptions;
import picocli.CommandLine;

import java.nio.file.Files;

@CommandSpec(requires = {"out.xml"}, produces = "processed.csv", dependsOn = {TestAnalysis.class})
@CommandSpec(
produces = "processed.csv",
dependsOn = @Dependency(value = TestAnalysis.class, files = {"out.xml"}, required = true)
)
public class TestOtherDependentAnalysis implements MATSimAppCommand {

@CommandLine.Mixin
Expand Down

0 comments on commit b69989f

Please sign in to comment.