use of org.openstreetmap.atlas.exception.CoreException in project atlas-checks by osmlab.
the class IntegrityCheckSparkJob method start.
@SuppressWarnings({ "rawtypes" })
@Override
public void start(final CommandMap commandMap) {
final String atlasDirectory = (String) commandMap.get(ATLAS_FOLDER);
final String input = Optional.ofNullable(input(commandMap)).orElse(atlasDirectory);
final String output = output(commandMap);
@SuppressWarnings("unchecked") final Set<OutputFormats> outputFormats = (Set<OutputFormats>) commandMap.get(OUTPUT_FORMATS);
final StringList countries = StringList.split((String) commandMap.get(COUNTRIES), CommonConstants.COMMA);
final MapRouletteConfiguration mapRouletteConfiguration = (MapRouletteConfiguration) commandMap.get(MAP_ROULETTE);
final Configuration checksConfiguration = ConfigurationResolver.loadConfiguration(commandMap, CONFIGURATION_FILES, CONFIGURATION_JSON);
final boolean saveIntermediateAtlas = (Boolean) commandMap.get(PBF_SAVE_INTERMEDIATE_ATLAS);
@SuppressWarnings("unchecked") final Rectangle pbfBoundary = ((Optional<Rectangle>) commandMap.getOption(PBF_BOUNDING_BOX)).orElse(Rectangle.MAXIMUM);
final boolean compressOutput = Boolean.valueOf((String) commandMap.get(SparkJob.COMPRESS_OUTPUT));
final Map<String, String> sparkContext = configurationMap();
final CheckResourceLoader checkLoader = new CheckResourceLoader(checksConfiguration);
// check configuration and country list
final Set<BaseCheck> preOverriddenChecks = checkLoader.loadChecks();
if (!isValidInput(countries, preOverriddenChecks)) {
logger.error("No countries supplied or checks enabled, exiting!");
return;
}
// Read priority countries from the configuration
final List<String> priorityCountries = checksConfiguration.get("priority.countries", Collections.EMPTY_LIST).value();
// Create a list of Country to Check tuples
// Add priority countries first if they are supplied by parameter
final List<Tuple2<String, Set<BaseCheck>>> countryCheckTuples = new ArrayList<>();
countries.stream().filter(priorityCountries::contains).forEach(country -> countryCheckTuples.add(new Tuple2<>(country, checkLoader.loadChecksForCountry(country))));
// Then add the rest of the countries
countries.stream().filter(country -> !priorityCountries.contains(country)).forEach(country -> countryCheckTuples.add(new Tuple2<>(country, checkLoader.loadChecksForCountry(country))));
// Log countries and integrity
logger.info("Initialized countries: {}", countryCheckTuples.stream().map(tuple -> tuple._1).collect(Collectors.joining(",")));
logger.info("Initialized checks: {}", preOverriddenChecks.stream().map(BaseCheck::getCheckName).collect(Collectors.joining(",")));
// Parallelize on the countries
final JavaPairRDD<String, Set<BaseCheck>> countryCheckRDD = getContext().parallelizePairs(countryCheckTuples, countryCheckTuples.size());
// Set target and temporary folders
final String targetOutputFolder = SparkFileHelper.parentPath(output);
final String temporaryOutputFolder = SparkFileHelper.combine(targetOutputFolder, SparkFileHelper.TEMPORARY_FOLDER_NAME);
// Useful file helper to create/delete/name files and directories
final SparkFileHelper fileHelper = new SparkFileHelper(sparkContext);
// Atlas Helper to load different types of Atlas data
final AtlasDataSource atlasLoader = new AtlasDataSource(sparkContext, checksConfiguration, pbfBoundary);
// Create target folders
fileHelper.mkdir(SparkFileHelper.combine(targetOutputFolder, OUTPUT_FLAG_FOLDER));
fileHelper.mkdir(SparkFileHelper.combine(targetOutputFolder, OUTPUT_GEOJSON_FOLDER));
fileHelper.mkdir(SparkFileHelper.combine(targetOutputFolder, OUTPUT_METRIC_FOLDER));
// Run the set of flags per country per check. The output will be an RDD pair mapping each
// country with a set of SparkFilePaths to flags, geojson and metrics generated.
final JavaPairRDD<String, Set<SparkFilePath>> resultRDD = countryCheckRDD.mapToPair(tuple -> {
final Time timer = Time.now();
final String country = tuple._1();
final Set<BaseCheck> checks = tuple._2();
logger.info("Initialized checks for {}: {}", country, checks.stream().map(BaseCheck::getCheckName).collect(Collectors.joining(",")));
final Set<SparkFilePath> resultingFiles = new HashSet<>();
final SparkFilePath flagOutput;
if (outputFormats.contains(OutputFormats.FLAGS)) {
// Initialize flag output processor
flagOutput = initializeOutput(OUTPUT_FLAG_FOLDER, TaskContext.get(), country, temporaryOutputFolder, targetOutputFolder);
EventService.get(country).register(new CheckFlagFileProcessor(fileHelper, flagOutput.getTemporaryPath()).withCompression(compressOutput));
} else {
flagOutput = null;
}
final SparkFilePath geoJsonOutput;
if (outputFormats.contains(OutputFormats.GEOJSON)) {
// Initialize geojson output processor
geoJsonOutput = initializeOutput(OUTPUT_GEOJSON_FOLDER, TaskContext.get(), country, temporaryOutputFolder, targetOutputFolder);
EventService.get(country).register(new CheckFlagGeoJsonProcessor(fileHelper, geoJsonOutput.getTemporaryPath()).withCompression(compressOutput));
} else {
geoJsonOutput = null;
}
final SparkFilePath metricOutput;
if (outputFormats.contains(OutputFormats.METRICS)) {
// Initialize metric output processor
metricOutput = initializeOutput(OUTPUT_METRIC_FOLDER, TaskContext.get(), country, temporaryOutputFolder, targetOutputFolder);
EventService.get(country).register(new MetricFileGenerator(METRICS_FILENAME, fileHelper, metricOutput.getTemporaryPath()));
} else {
metricOutput = null;
}
final Consumer<Atlas> intermediateAtlasHandler;
if (saveIntermediateAtlas) {
final SparkFilePath atlasOutput = initializeOutput(OUTPUT_ATLAS_FOLDER, TaskContext.get(), country, temporaryOutputFolder, targetOutputFolder);
intermediateAtlasHandler = atlas -> {
writeAtlas(atlas, country, atlasOutput, fileHelper);
resultingFiles.add(atlasOutput);
};
} else {
intermediateAtlasHandler = atlas -> {
// no-op
};
}
try {
final Atlas atlas = atlasLoader.load(input, country, intermediateAtlasHandler);
if (atlas == null) {
logger.error("Could not find {} Atlas files. Skipping country!", country);
} else {
executeChecks(country, atlas, checks, mapRouletteConfiguration);
// Add output folders for handling later
Stream.of(flagOutput, metricOutput, geoJsonOutput).filter(Objects::nonNull).forEach(resultingFiles::add);
}
EventService.get(country).complete();
return new Tuple2<>(country, resultingFiles);
} catch (final CoreException e) {
logger.error("Exception running integrity checks on {}", country, e);
}
logger.trace("Integrity checks took {} ms to execute for {}.", timer.elapsedSince().asMilliseconds(), country);
return new Tuple2<>(IGNORED_KEY, null);
}).filter(tuple -> !tuple._1().equals(IGNORED_KEY));
// Commit results
resultRDD.foreach(countryPathPair -> {
final String country = countryPathPair._1();
final Set<SparkFilePath> paths = countryPathPair._2();
logger.info("[{}] Committing outputs: {}", country, paths);
paths.forEach(fileHelper::commit);
});
try {
// Clean up
logger.info("Deleting {}.", temporaryOutputFolder);
fileHelper.deleteDirectory(temporaryOutputFolder);
} catch (final Exception e) {
logger.warn("Clean up failed!", e);
}
}
use of org.openstreetmap.atlas.exception.CoreException in project atlas-checks by osmlab.
the class ConfigurationResolver method loadConfiguration.
/**
* Resolves a {@link Configuration} for {@link Command}s given the {@link CommandMap} and
* {@link Command.Switch}s available
*
* @param commandMap
* the {@link Command}'s {@link CommandMap}
* @param keyFiles
* the {@link Command.Switch} containing a list of URIs for configuration
* @param keyJson
* the {@link Command.Switch} containing inline JSON configuration
* @return a new {@link Configuration}
*/
public static Configuration loadConfiguration(final CommandMap commandMap, final Command.Switch<StringList> keyFiles, final Command.Switch<String> keyJson) {
final List<InputStream> configurationSources = new ArrayList<>();
ConfigurationResolver.getResourceAsStream("application.json").ifPresent(configurationSources::add);
commandMap.getOption(keyFiles).ifPresent(files -> ((StringList) files).forEach(uri -> ConfigurationResolver.getResourceAsStream(URI.create(uri)).ifPresent(configurationSources::add)));
commandMap.getOption(keyJson).map(value -> new ByteArrayInputStream(value.toString().getBytes(StandardCharsets.UTF_8))).ifPresent(configurationSources::add);
final List<Resource> configurationResources = configurationSources.stream().map(InputStreamResource::new).collect(Collectors.toList());
final Configuration configuration;
Throwable thrown = null;
try {
configuration = new MergedConfiguration(Iterables.head(configurationResources), Iterables.tail(configurationResources));
} finally {
for (final InputStream source : configurationSources) {
try {
source.close();
} catch (final Throwable throwable) {
thrown = throwable;
}
}
}
if (thrown != null) {
throw new CoreException("Failed to load configuration", thrown);
}
return configuration;
}
use of org.openstreetmap.atlas.exception.CoreException in project atlas-checks by osmlab.
the class Task method generateTaskFeatures.
protected JsonArray generateTaskFeatures(final Set<PointInformation> source, final Optional<JsonArray> geoJson) {
final JsonArray features = new JsonArray();
if (source.isEmpty() && !geoJson.isPresent()) {
throw new CoreException("Could not find any features for the task [{}].", this.toString());
}
source.forEach(point -> {
final JsonObject feature = new JsonObject();
final JsonObject geometry = new JsonObject();
final JsonArray coordinates = new JsonArray();
coordinates.add(new JsonPrimitive(point.getLocation().getLongitude().asDegrees()));
coordinates.add(new JsonPrimitive(point.getLocation().getLatitude().asDegrees()));
geometry.add(TASK_TYPE, new JsonPrimitive(POINT));
geometry.add(TASK_FEATURE_COORDINATES, coordinates);
feature.add(TASK_FEATURE_GEOMETRY, geometry);
feature.add(TASK_TYPE, new JsonPrimitive(FEATURE));
final JsonObject pointInformation = new JsonObject();
point.getDescription().ifPresent(description -> pointInformation.add(KEY_DESCRIPTION, new JsonPrimitive(description)));
feature.add(TASK_FEATURE_PROPERTIES, pointInformation);
features.add(feature);
});
geoJson.ifPresent(json -> json.forEach(features::add));
return features;
}
use of org.openstreetmap.atlas.exception.CoreException in project atlas-checks by osmlab.
the class SelfIntersectingPolylineCheck method flag.
@Override
protected Optional<CheckFlag> flag(final AtlasObject object) {
final Optional<CheckFlag> response;
final int localizedInstructionIndex;
final PolyLine polyline;
if (object instanceof Edge) {
polyline = ((Edge) object).asPolyLine();
// Send building instructions if building tag exists
localizedInstructionIndex = (TagPredicates.IS_BUILDING.test(object)) ? 2 : 0;
} else if (object instanceof Line) {
polyline = ((Line) object).asPolyLine();
// Send building instructions if building tag exists
localizedInstructionIndex = (TagPredicates.IS_BUILDING.test(object)) ? 2 : 0;
} else if (object instanceof Area) {
polyline = ((Area) object).asPolygon();
// Send duplicate Edge instructions if duplicate Edges exist
localizedInstructionIndex = hasDuplicateSegments(polyline) ? THREE : 1;
} else {
throw new CoreException("Invalid item type {}", object.getClass().toString());
}
// First, find shape point intersections
final Set<Location> selfIntersections = polyline.selfIntersections();
if (selfIntersections.size() > 0) {
final CheckFlag flag = new CheckFlag(Long.toString(object.getIdentifier()));
flag.addObject(object);
flag.addInstruction(this.getLocalizedInstruction(localizedInstructionIndex, object.getOsmIdentifier(), selfIntersections.toString()));
selfIntersections.forEach(flag::addPoint);
response = Optional.of(flag);
} else {
// Next, find intersections occurring at non-shape points using JTS verification
boolean isJtsValid = true;
try {
if (object instanceof Area) {
isJtsValid = GeometryValidator.isValidPolygon((Polygon) polyline);
} else {
isJtsValid = GeometryValidator.isValidPolyLine(polyline);
}
} catch (final IllegalArgumentException e) {
// Invalid geometry found when converting the PolyLine/Polygon.
// This can be a number of cases. For example, a LineString expects exactly 0 or >=2
// points or a Polygon expects 0 or >= 4 points. This isn't self-intersecting
// geometry, but rather inconsistent geometry, according to JTS.
logger.error("Encountered invalid geometry for feature {}", object.getOsmIdentifier(), e);
}
if (!isJtsValid) {
response = Optional.of(createFlag(object, this.getLocalizedInstruction(localizedInstructionIndex)));
} else {
response = Optional.empty();
}
}
return response;
}
use of org.openstreetmap.atlas.exception.CoreException in project atlas-checks by osmlab.
the class CheckResourceLoader method loadChecks.
/**
* Loads checks that are enabled by some other means, defined by {@code isEnabled}
*
* @param isEnabled
* {@link Predicate} used to determine if a check is enabled
* @param configuration
* {@link Configuration} used to loadChecks {@link CheckResourceLoader}
* @param <T>
* check type
* @return a {@link Set} of checks
*/
@SuppressWarnings("unchecked")
public <T extends Check> Set<T> loadChecks(final Predicate<Class> isEnabled, final Configuration configuration) {
final Set<T> checks = new HashSet<>();
final Time time = Time.now();
try {
final ClassPath classPath = ClassPath.from(Thread.currentThread().getContextClassLoader());
packages.forEach(packageName -> classPath.getTopLevelClassesRecursive(packageName).forEach(classInfo -> {
final Class<?> checkClass = classInfo.load();
if (checkType.isAssignableFrom(checkClass) && !Modifier.isAbstract(checkClass.getModifiers()) && isEnabled.test(checkClass)) {
try {
Object check;
try {
check = checkClass.getConstructor(Configuration.class).newInstance(configuration);
} catch (final InvocationTargetException oops) {
throw new CoreException("Unable to create a configurable instance of {}", checkClass.getSimpleName(), oops);
} catch (final NoSuchMethodException oops) {
check = checkClass.newInstance();
}
if (check != null) {
checks.add((T) check);
}
} catch (final ClassCastException | InstantiationException | IllegalAccessException oops) {
logger.error("Failed to instantiate {}, ignoring. Reason: {}", checkClass.getName(), oops.getMessage());
}
}
}));
} catch (final IOException oops) {
throw new CoreException("Failed to discover {} classes on classpath", checkType.getSimpleName());
}
logger.info("Loaded {} {} in {}", checks.size(), checkType.getSimpleName(), time.elapsedSince());
return checks;
}
Aggregations