diff --git a/.github/workflow_scripts/deploy.sh b/.github/workflow_scripts/deploy.sh index 1247fdad17..ce814df9f8 100644 --- a/.github/workflow_scripts/deploy.sh +++ b/.github/workflow_scripts/deploy.sh @@ -12,7 +12,7 @@ then if [ "$MANUAL_RELEASE_TRIGGERED" = "true" ]; then echo "Sign, Upload archives to local repo, Upload archives to Sonatype, Close and release repository." - ./gradlew uploadArchives publishToNexusAndClose + ./gradlew publishAllPublicationsToMavenRepository publishAllPublicationsToSnapshotRepository #python -m pip install --user --upgrade twine #twine upload ./pyatlas/dist/* else diff --git a/build.gradle b/build.gradle index 8ad889a75f..8b7f8feef9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,15 +1,15 @@ plugins { - id 'java' + id 'checkstyle' id 'groovy' - id 'maven' - id 'maven-publish' id 'idea' - id 'signing' - id 'checkstyle' id 'jacoco' - id "com.diffplug.gradle.spotless" version "3.27.0" - id 'org.sonarqube' version '2.8' - id 'com.google.protobuf' version '0.8.8' + id 'java' + id 'java-library' + id 'maven-publish' + id 'signing' + id 'com.diffplug.spotless' version '6.3.0' + id 'com.google.protobuf' version '0.8.18' + id 'org.sonarqube' version '3.3' } apply from: 'dependencies.gradle' @@ -38,62 +38,66 @@ repositories configurations { - shaded + shaded.extendsFrom(implementation) } dependencies { - compile packages.slf4j.api - compile packages.opencsv - compile packages.gson - compile packages.http - compile packages.jts - compile packages.spatial4j - compile packages.geotools - compile packages.osmosis.core - compile packages.osmosis.pbf - compile packages.osmosis.xml - compile packages.osmosis.hstore - compile packages.commons.cli - compile packages.commons.csv - compile packages.commons.io - compile packages.commons.lang - compile packages.commons.math - compile packages.commons.text - compile packages.classgraph - compile packages.guava - compile packages.jsonassert - compile packages.jackson.core - compile packages.jackson.databind - compile packages.jackson.dataformat + implementation packages.artifact + implementation packages.checkstyle + api packages.classgraph + implementation packages.commons.cli + implementation packages.commons.compress + implementation packages.commons.csv + implementation packages.commons.io + implementation packages.commons.lang + implementation packages.commons.math + implementation packages.commons.text + implementation packages.diff_utils + implementation packages.geotools + api packages.groovy + implementation packages.groovy_json + implementation packages.gson + api packages.guava + api packages.http + api packages.jackson.core + api packages.jackson.databind + api packages.jackson.dataformat + api packages.jim_fs + implementation packages.jsonassert + api packages.jts // Support JUnit 3/4 tests - compile packages.junit.junit4 - compile packages.protobuf_java - compile packages.protoc - compile packages.artifact - compile packages.groovy - compile packages.checkstyle - compile packages.diff_utils - compile packages.groovy_json - compile packages.jim_fs - - testCompile packages.checkstyle_tests - testCompile packages.junit.api - testCompile packages.junit.engine - testCompile packages.junit.params - testCompile packages.junit.vintage - + api packages.junit.junit4 // only API level due to CoreTestRule + implementation packages.opencsv + api packages.osmosis.core + implementation packages.osmosis.hstore + implementation packages.osmosis.osmbinary + implementation packages.osmosis.pbf + implementation packages.osmosis.xml + implementation packages.protobuf_java + implementation packages.protoc + implementation packages.slf4j.api + implementation packages.spatial4j + + testImplementation packages.checkstyle_tests + // Google Truth is needed for checkstyle tests (as of checkstyle 9.2.1) + testImplementation packages.google_truth + testImplementation packages.junit.api + testImplementation packages.junit.engine + testImplementation packages.junit.junit4 + testImplementation packages.junit.params + testImplementation packages.junit.vintage + + checkstyle files("build/libs/${project.name}-${project.version}.jar") checkstyle packages.checkstyle - checkstyle packages.atlas_checkstyle - shaded project.configurations.getByName('compile') shaded packages.log4j.api shaded packages.log4j.slf4j } task shaded(type: Jar) { - baseName = project.name + archiveBaseName = project.name classifier = 'shaded' from { @@ -143,3 +147,19 @@ idea { languageLevel = '1.8' } } + +/* + * Workaround Gradle not liking duplicate files + * I suspect that it is due to fake duplicates. + * For more information, see https://github.com/gradle/gradle/issues/17236 + * (AKA, remove this when that issue is fixed) + * + * Note: It may be useful to disable this from time to time on Gradle update + * to see if either it is fixed or if there is better debugging + * information available. + */ +tasks.each { + task -> if (task.hasProperty("duplicatesStrategy")) { + task.setProperty("duplicatesStrategy", "EXCLUDE") + } +} diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index e3cbff6157..6acb1ad3be 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -8,10 +8,7 @@ - - - - + @@ -43,7 +40,18 @@ - + diff --git a/dependencies.gradle b/dependencies.gradle index 2d9abfaa3e..951b1ddb97 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -1,37 +1,39 @@ project.ext.versions = [ - checkstyle: '8.18', - junit4: '4.13.1', - junit5: '5.8.1', - jacoco: '0.8.3', + checkstyle: '9.3', + junit4: '4.13.2', + junit5: '5.8.2', + jacoco: '0.8.7', slf4j: '1.7.32', log4j: '2.17.1', opencsv: '2.3', - gson: '2.2.4', - http: '4.5.1', + gson: '2.9.0', + http: '4.5.13', jts: '1.18.2', - spatial4j: '0.7', - geotools: '24.0', - osmosis: '0.44.1', - commons_cli: '1.3.1', - commons_csv: '1.2', - commons_io: '2.5', - commons_lang: '3.9', - commons_math: '3.3', - commons_text: '1.8', - classgraph: '4.6.32', - guava: '27.0.1-jre', - jsonassert:'1.3.0', - jackson_core:'2.10.5', - jackson_databind:'2.10.5', - jackson_dataformat_yaml:'2.10.5', - protobuf_java:'2.6.1', - protoc:'2.6.1', - artifact:'3.5.4', - groovy: '2.5.4', - atlas_checkstyle: '5.6.9', + spatial4j: '0.8', + geotools: '26.2', + osmosis: '0.48.3', + commons_cli: '1.5.0', + commons_compress: '1.21', + commons_csv: '1.9.0', + commons_io: '2.11.0', + commons_lang: '3.12.0', + commons_math: '3.6.1', + commons_text: '1.9', + classgraph: '4.8.139', + guava: '31.0.1-jre', + google_truth: '1.1.3', + jsonassert:'1.5.0', + jackson_core:'2.13.1', + jackson_databind:'2.13.1', + jackson_dataformat_yaml:'2.13.1', + protobuf_java:'3.19.1', + protoc:'3.19.1', + artifact:'3.8.4', + groovy: '3.0.9', + atlas_checkstyle: '6.6.1', diff_utils: '4.0', - groovy_json: '2.5.4', - jim_fs: '1.1' + groovy_json: '3.0.9', + jim_fs: '1.2' ] project.ext.packages = [ @@ -50,6 +52,7 @@ project.ext.packages = [ slf4j: "org.apache.logging.log4j:log4j-slf4j-impl:${versions.log4j}", ], opencsv: "net.sf.opencsv:opencsv:${versions.opencsv}", + google_truth: "com.google.truth:truth:${versions.google_truth}", gson: "com.google.code.gson:gson:${versions.gson}", http: "org.apache.httpcomponents:httpclient:${versions.http}", jts: "org.locationtech.jts:jts-core:${versions.jts}", @@ -57,13 +60,15 @@ project.ext.packages = [ geotools: "org.geotools:gt-shapefile:${versions.geotools}", osmosis: [ core: "org.openstreetmap.osmosis:osmosis-core:${versions.osmosis}", - pbf: "org.openstreetmap.osmosis:osmosis-pbf:${versions.osmosis}", - xml: "org.openstreetmap.osmosis:osmosis-xml:${versions.osmosis}", hstore:"org.openstreetmap.osmosis:osmosis-hstore-jdbc:${versions.osmosis}", + osmbinary: "org.openstreetmap.osmosis:osmosis-osm-binary:${versions.osmosis}", + pbf: "org.openstreetmap.osmosis:osmosis-pbf:${versions.osmosis}", pg:"org.openstreetmap.osmosis:osmosis-pgsnapshot:${versions.osmosis}", + xml: "org.openstreetmap.osmosis:osmosis-xml:${versions.osmosis}", ], commons:[ cli: "commons-cli:commons-cli:${versions.commons_cli}", + compress: "org.apache.commons:commons-compress:${versions.commons_compress}", csv : "org.apache.commons:commons-csv:${versions.commons_csv}", io: "commons-io:commons-io:${versions.commons_io}", lang: "org.apache.commons:commons-lang3:${versions.commons_lang}", diff --git a/gradle/deployment.gradle b/gradle/deployment.gradle index f453813e55..fb2b08ad18 100644 --- a/gradle/deployment.gradle +++ b/gradle/deployment.gradle @@ -23,79 +23,58 @@ signing sign configurations.archives } -uploadArchives +publishing { - doFirst { - mkdir "file:/$rootDir/build/deploy" - } - repositories + publications { - mavenDeployer + mavenJava(MavenPublication) { - beforeDeployment - { - MavenDeployment deployment -> signing.signPom(deployment) - } - - // Hack: Deploy to a local repository first, then upload to Sonatype using scripts. - repository(url: "file://localhost/$rootDir/build/deploy" /*maven2_url*/) { - authentication(userName: System.getenv('SONATYPE_USERNAME'), password: System.getenv('SONATYPE_PASSWORD')) - } - - snapshotRepository(url: "file://localhost/$rootDir/build/deploy" /*snapshot_url*/) { - authentication(userName: System.getenv('SONATYPE_USERNAME'), password: System.getenv('SONATYPE_PASSWORD')) - } - - pom.project + pom { - name project_name - packaging 'jar' + name = project_name + packaging = 'jar' // optionally artifactId can be defined here - description project_description - url project_url + description = project_description + url = project_url scm { - connection project_scm - developerConnection project_scm - url project_url + connection = project_scm + developerConnection = project_scm + url = project_url } licenses { license { - name project_license_slug - url project_license_url + name = project_license_slug + url = project_license_url } } developers { developer { - id project_developer - name project_developer + id = project_developer + name = project_developer } } } } } -} - -// Scripted hack, inpired from: -// https://github.com/h2oai/sparkling-water/tree/3f8fcf387a2bcc080343a8fafdc81aebc0d99fa1/gradle/publish -// and -// https://github.com/h2oai/sparkling-water/blob/73d2e2bd11ce35c6379f6961188fb2af1a7bc04b/build.gradle#L228 -// and -// https://support.sonatype.com/hc/en-us/articles/213465868-Uploading-to-a-Staging-Repository-via-REST-API -// and -// https://support.sonatype.com/hc/en-us/articles/213465448-Automatically-dropping-old-staging-repositories -// Until either this one works for us: https://github.com/marcphilipp/nexus-publish-plugin -// or this issue is fixed another way: -// https://github.com/travis-ci/travis-ci/issues/9555 -def uploadAndRelease(def username, def password, def repoDir) { - def proc = ['./uploadAndRelease.sh', username, password, repoDir].execute([], file("${rootDir.toString()}/gradle")) - proc.waitForProcessOutput(System.out, System.err) -} - -task publishToNexusAndClose(dependsOn: 'publish'){ - doLast { - uploadAndRelease(System.getenv('SONATYPE_USERNAME'), System.getenv('SONATYPE_PASSWORD'), "$rootDir/build/deploy") + repositories { + // Hack: Deploy to a local repository first, then upload to Sonatype using scripts. + maven { + url = "https://oss.sonatype.org/service/local/staging/deploy/maven2/" // maven2_url + credentials { + username System.getenv('SONATYPE_USERNAME') + password System.getenv('SONATYPE_PASSWORD') + } + } + maven { + url = "https://s01.oss.sonatype.org/content/repositories/snapshots" // snapshot_url + name = "snapshot" + credentials { + username System.getenv('SONATYPE_USERNAME') + password System.getenv('SONATYPE_PASSWORD') + } + } } } diff --git a/gradle/quality.gradle b/gradle/quality.gradle index 5cef323ad6..ce7680f694 100644 --- a/gradle/quality.gradle +++ b/gradle/quality.gradle @@ -53,6 +53,8 @@ checkstyleIntegrationTest.dependsOn jar check.dependsOn integrationTest integrationTest.mustRunAfter test +jacocoTestReport.dependsOn test +jacocoTestReport.dependsOn integrationTest check.dependsOn jacocoTestReport tasks.withType(Test) { @@ -61,22 +63,19 @@ tasks.withType(Test) { configurations { - integrationTestCompile.extendsFrom testCompile + integrationTestImplementation.extendsFrom testImplementation integrationTestRuntime.extendsFrom testRuntime } dependencies { - testCompile packages.log4j.slf4j - testCompile packages.log4j.api + testImplementation packages.log4j.slf4j + testImplementation packages.log4j.api // Support Junit 5 tests testImplementation packages.junit.api testRuntimeOnly packages.junit.engine // Support JUnit 3/4 tests - testCompile packages.junit.junit4 - testRuntimeOnly packages.junit.vintage - - integrationTestCompile packages.junit.junit4 + testImplementation packages.junit.junit4 testRuntimeOnly packages.junit.vintage } @@ -97,8 +96,8 @@ spotless { jacocoTestReport { reports { - xml.enabled true - csv.enabled true + xml.required = true + csv.required = true html.destination file("${buildDir}/reports/jacoco") } // Below, works with gradle 6 diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index e708b1c023..7454180f2a 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index da9702f9e7..1debed0d8f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.8-bin.zip +distributionSha256Sum=8cc27038d5dbd815759851ba53e70cf62e481b87494cc97cfd97982ada5ba634 +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index 4f906e0c81..1b6c787337 100755 --- a/gradlew +++ b/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,101 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +APP_BASE_NAME=${0##*/} # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,95 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/src/main/java/org/openstreetmap/atlas/geography/Segment.java b/src/main/java/org/openstreetmap/atlas/geography/Segment.java index c6f1d757f3..6c811a06e5 100644 --- a/src/main/java/org/openstreetmap/atlas/geography/Segment.java +++ b/src/main/java/org/openstreetmap/atlas/geography/Segment.java @@ -56,6 +56,36 @@ private static List asList(final Location start, final Location end) return result; } + /** + * Ensures that numerator/denominator is within the range [0,1] without doing the division + * + * @param denominator + * The denominator of the fraction + * @param numerator + * The numerator of the fraction + * @return {@code true} if the fraction is in the range [0,1] + */ + private static boolean rangeCheck(final double denominator, final double numerator) + { + return denominator > 0 && (numerator < 0 || numerator > denominator) + || denominator < 0 && (numerator > 0 || numerator < denominator); + } + + /** + * Ensures that numerator/denominator is within the range [0,1] without doing the division + * + * @param denominator + * The denominator of the fraction + * @param numerator + * The numerator of the fraction + * @return {@code true} if the fraction is in the range [0,1] + */ + private static boolean rangeCheck(final long denominator, final long numerator) + { + return denominator > 0 && (numerator < 0 || numerator > denominator) + || denominator < 0 && (numerator > 0 || numerator < denominator); + } + public Segment(final Location start, final Location end) { super(asList(start, end)); @@ -184,19 +214,14 @@ public boolean intersects(final Segment that) final long alphaNumerator = Math.subtractExact(byAxis * cxAxis, bxAxis * cyAxis); final long commonDenominator = Math.subtractExact(ayAxis * bxAxis, axAxis * byAxis); // ensures that alpha is within the range [0,1] without doing the division - if ((commonDenominator > 0 - && (alphaNumerator < 0 || alphaNumerator > commonDenominator)) - || (commonDenominator < 0 - && (alphaNumerator > 0 || alphaNumerator < commonDenominator))) + if (rangeCheck(commonDenominator, alphaNumerator)) { return false; } final long betaNumerator = Math.subtractExact(axAxis * cyAxis, ayAxis * cxAxis); // ensures that beta is within the range [0,1] without doing the division - if ((commonDenominator > 0 && (betaNumerator < 0 || betaNumerator > commonDenominator)) - || (commonDenominator < 0 - && (betaNumerator > 0 || betaNumerator < commonDenominator))) + if (rangeCheck(commonDenominator, betaNumerator)) { return false; } @@ -383,18 +408,14 @@ private boolean intersectsApproximate(final Segment that) final double alphaNumerator = byAxis * cxAxis - bxAxis * cyAxis; final double commonDenominator = ayAxis * bxAxis - axAxis * byAxis; // ensures that alpha is within the range [0,1] without doing the division - if ((commonDenominator > 0 && (alphaNumerator < 0 || alphaNumerator > commonDenominator)) - || (commonDenominator < 0 - && (alphaNumerator > 0 || alphaNumerator < commonDenominator))) + if (rangeCheck(commonDenominator, alphaNumerator)) { return false; } final double betaNumerator = axAxis * cyAxis - ayAxis * cxAxis; // ensures that beta is within the range [0,1] without doing the division - if ((commonDenominator > 0 && (betaNumerator < 0 || betaNumerator > commonDenominator)) - || (commonDenominator < 0 - && (betaNumerator > 0 || betaNumerator < commonDenominator))) + if (rangeCheck(commonDenominator, betaNumerator)) { return false; } diff --git a/src/main/java/org/openstreetmap/atlas/geography/atlas/change/ChangeEntity.java b/src/main/java/org/openstreetmap/atlas/geography/atlas/change/ChangeEntity.java index 02cdf65ff2..7def2f1819 100644 --- a/src/main/java/org/openstreetmap/atlas/geography/atlas/change/ChangeEntity.java +++ b/src/main/java/org/openstreetmap/atlas/geography/atlas/change/ChangeEntity.java @@ -42,9 +42,13 @@ static Set filterRelations(final Set listed, final ChangeAtl * The source entity * @param memberExtractor * Extract the member attribute from that entity + * @param + * The entity type that some object will be extracted from + * @param + * The object type that will be extracted and returned * @return The corresponding attribute */ - static T getAttribute(final M source, + static T getAttribute(final M source, final Function memberExtractor) { T result = null; @@ -67,11 +71,14 @@ static T getAttribute(final M source, * The change entity (override) * @param memberExtractor * Extract the member attribute from that entity + * @param + * The entity type to extract information from + * @param + * The type that will be extracted from the entity * @return The corresponding attribute list. Will not be empty. */ - static List getAttributeAndOptionallyBackup( - final M source, final M override, final Function memberExtractor, - final String name) + static List getAttributeAndOptionallyBackup(final M source, + final M override, final Function memberExtractor, final String name) { final List result = new ArrayList<>(); if (override != null) @@ -112,10 +119,14 @@ static List getAttributeAndOptional * The change entity (override) * @param memberExtractor * Extract the member attribute from that entity + * @param + * The atlas entity type that will be extracted from + * @param + * The expected return type * @return The corresponding attribute */ - static T getAttributeOrBackup(final M source, - final M override, final Function memberExtractor, final String name) + static T getAttributeOrBackup(final M source, final M override, + final Function memberExtractor, final String name) { T result = null; if (override != null) diff --git a/src/main/java/org/openstreetmap/atlas/geography/atlas/dynamic/DynamicAtlasExpander.java b/src/main/java/org/openstreetmap/atlas/geography/atlas/dynamic/DynamicAtlasExpander.java index 1c9a7ac541..9847358c2e 100644 --- a/src/main/java/org/openstreetmap/atlas/geography/atlas/dynamic/DynamicAtlasExpander.java +++ b/src/main/java/org/openstreetmap/atlas/geography/atlas/dynamic/DynamicAtlasExpander.java @@ -176,6 +176,10 @@ void buildUnderlyingMultiAtlas() * @param mapper * What to do with the result. This is to replace the regular items with * DynamicItems. + * @param + * The object type the returned iterable will return + * @param + * The original entity type * @return The {@link Iterable} of DynamicItems */ Iterable expand(final Supplier> entitiesSupplier, diff --git a/src/main/java/org/openstreetmap/atlas/geography/atlas/items/complex/bignode/BigNodeFinder.java b/src/main/java/org/openstreetmap/atlas/geography/atlas/items/complex/bignode/BigNodeFinder.java index fc06baa35e..bf24c02e8f 100644 --- a/src/main/java/org/openstreetmap/atlas/geography/atlas/items/complex/bignode/BigNodeFinder.java +++ b/src/main/java/org/openstreetmap/atlas/geography/atlas/items/complex/bignode/BigNodeFinder.java @@ -720,7 +720,7 @@ private boolean isDualCarriageWayRoute(final Route candidateRoute) if (outEdge.highwayTag().isMoreImportantThanOrEqualTo(HighwayTag.UNCLASSIFIED) // if an edge is considered as a junction edge, the dual carriage way // it connects to can not be link road - && (!inEdge.highwayTag().isLink() && !outEdge.highwayTag().isLink()) + && !inEdge.highwayTag().isLink() && !outEdge.highwayTag().isLink() && this.edgeDirectionComparator.isOppositeDirection(inEdge, outEdge, false) && !outEdge.hasReverseEdge() && !inEdge.hasReverseEdge() diff --git a/src/main/java/org/openstreetmap/atlas/geography/atlas/raw/creation/OsmPbfCounter.java b/src/main/java/org/openstreetmap/atlas/geography/atlas/raw/creation/OsmPbfCounter.java index 4907fc80f9..9908b1fdb3 100644 --- a/src/main/java/org/openstreetmap/atlas/geography/atlas/raw/creation/OsmPbfCounter.java +++ b/src/main/java/org/openstreetmap/atlas/geography/atlas/raw/creation/OsmPbfCounter.java @@ -95,6 +95,20 @@ public OsmPbfCounter(final AtlasLoadingOption loadingOption, final GeometricSurf this.boundingBox = boundingBox; } + @Override + public void close() + { + // Process all staged Relations + processStagedRelations(); + + // Grab any bridges, ferries or other ways that may be outside the immediate boundary + bringInConnectedOutsideWays(); + + // Combine all included nodes into a single collection + this.nodeIdentifiersToInclude.addAll(this.nodeIdentifiersBroughtInByWaysOrRelations); + logger.info("Released OSM PBF Counter"); + } + @Override public void complete() { @@ -209,20 +223,6 @@ public long relationCount() return this.relationIdentifiersToInclude.size(); } - @Override - public void release() - { - // Process all staged Relations - processStagedRelations(); - - // Grab any bridges, ferries or other ways that may be outside the immediate boundary - bringInConnectedOutsideWays(); - - // Combine all included nodes into a single collection - this.nodeIdentifiersToInclude.addAll(this.nodeIdentifiersBroughtInByWaysOrRelations); - logger.info("Released OSM PBF Counter"); - } - private void addWayNodes(final Set set, final Way way) { way.getWayNodes().forEach(wayNode -> set.add(wayNode.getNodeId())); diff --git a/src/main/java/org/openstreetmap/atlas/geography/atlas/raw/creation/OsmPbfReader.java b/src/main/java/org/openstreetmap/atlas/geography/atlas/raw/creation/OsmPbfReader.java index 6664660d4d..b484eb4553 100644 --- a/src/main/java/org/openstreetmap/atlas/geography/atlas/raw/creation/OsmPbfReader.java +++ b/src/main/java/org/openstreetmap/atlas/geography/atlas/raw/creation/OsmPbfReader.java @@ -127,6 +127,16 @@ public OsmPbfReader(final AtlasLoadingOption loadingOption, final PackedAtlasBui this.loadingOption = loadingOption; } + @Override + public void close() + { + // We've processed all Nodes, Ways and shallow Relations to this point. Now, we need to + // handle Relations that contain Relation members properly. + this.processStagedRelations(); + this.statistics.summary(); + logger.info("Released OSM PBF Reader"); + } + @Override public void complete() { @@ -174,16 +184,6 @@ else if (rawEntity instanceof Bound) } } - @Override - public void release() - { - // We've processed all Nodes, Ways and shallow Relations to this point. Now, we need to - // handle Relations that contain Relation members properly. - processStagedRelations(); - this.statistics.summary(); - logger.info("Released OSM PBF Reader"); - } - /** * Sets all the Node identifiers marked for inclusion. * @@ -493,7 +493,7 @@ private void processNode(final Entity entity) * Tries to create an Atlas {@link org.openstreetmap.atlas.geography.atlas.items.Relation}. If * the {@link Entity} contains a member that's also a relation and that member hasn't been * processed yet, then we add the given {@link Relation} to a Collection of staged relations to - * process later (see {@link #release()} method). Otherwise, we add it. + * process later (see {@link #close()} method). Otherwise, we add it. * * @param entity * The {@link Entity} that will become an Atlas diff --git a/src/main/java/org/openstreetmap/atlas/geography/geojson/parser/mapper/impl/DefaultBeanUtilsBasedMapperImpl.java b/src/main/java/org/openstreetmap/atlas/geography/geojson/parser/mapper/impl/DefaultBeanUtilsBasedMapperImpl.java index ab782ff684..ca55d78968 100644 --- a/src/main/java/org/openstreetmap/atlas/geography/geojson/parser/mapper/impl/DefaultBeanUtilsBasedMapperImpl.java +++ b/src/main/java/org/openstreetmap/atlas/geography/geojson/parser/mapper/impl/DefaultBeanUtilsBasedMapperImpl.java @@ -57,12 +57,12 @@ private T create(final Class targetClass) try { - return targetClass.newInstance(); + return targetClass.getConstructor().newInstance(); } - catch (final Exception e) + catch (final ReflectiveOperationException reflectiveOperationException) { throw new IllegalStateException("Failed to construct instance of class: " + targetClass - + "; isArray: " + targetClass.isArray(), e); + + "; isArray: " + targetClass.isArray(), reflectiveOperationException); } } @@ -155,7 +155,7 @@ else if (!propertyType.isArray()) catch (final Exception e) { throw new IllegalStateException( - "Population fialed. map: " + map + "; bean: " + bean + ".", e); + "Population failed. map: " + map + "; bean: " + bean + ".", e); } } } diff --git a/src/main/java/org/openstreetmap/atlas/tags/filters/matcher/parsing/SemanticChecker.java b/src/main/java/org/openstreetmap/atlas/tags/filters/matcher/parsing/SemanticChecker.java index 9b6d908ce6..266826575c 100644 --- a/src/main/java/org/openstreetmap/atlas/tags/filters/matcher/parsing/SemanticChecker.java +++ b/src/main/java/org/openstreetmap/atlas/tags/filters/matcher/parsing/SemanticChecker.java @@ -24,7 +24,7 @@ public void check(final ASTNode root) return; } - if ((root instanceof EqualsOperator) && subtreeContainsEquals(root)) + if (root instanceof EqualsOperator && this.subtreeContainsEquals(root)) { throw new CoreException("semantic error: invalid nested equality operators"); } diff --git a/src/main/java/org/openstreetmap/atlas/utilities/identifiers/EntityIdentifierGenerator.java b/src/main/java/org/openstreetmap/atlas/utilities/identifiers/EntityIdentifierGenerator.java index 3c43401a6a..106da32bdc 100644 --- a/src/main/java/org/openstreetmap/atlas/utilities/identifiers/EntityIdentifierGenerator.java +++ b/src/main/java/org/openstreetmap/atlas/utilities/identifiers/EntityIdentifierGenerator.java @@ -310,7 +310,7 @@ private long generate(final CompleteEntity entity, final boolean allowNegativ UUID entityHash = UUID.nameUUIDFromBytes(entityString.getBytes()); long shortHash = entityHash.getMostSignificantBits(); - while (!isHashSafeToUse(shortHash) || (shortHash < 0 && !allowNegativeIdentifiers)) + while (!this.isHashSafeToUse(shortHash) || shortHash < 0 && !allowNegativeIdentifiers) { entityHash = UUID.nameUUIDFromBytes(entityHash.toString().getBytes()); shortHash = entityHash.getMostSignificantBits(); diff --git a/src/main/java/org/openstreetmap/atlas/utilities/testing/OsmosisXmlReaderFromResource.java b/src/main/java/org/openstreetmap/atlas/utilities/testing/OsmosisXmlReaderFromResource.java index 17306b420d..8b41caf5cb 100644 --- a/src/main/java/org/openstreetmap/atlas/utilities/testing/OsmosisXmlReaderFromResource.java +++ b/src/main/java/org/openstreetmap/atlas/utilities/testing/OsmosisXmlReaderFromResource.java @@ -41,6 +41,25 @@ public class OsmosisXmlReaderFromResource implements RunnableSource private final boolean enableDateParsing; private final CompressionMethod compressionMethod; + /** + * Creates a new SAX parser. + * + * @return The newly created SAX parser. + */ + private static SAXParser createParser() + { + try + { + final SAXParserFactory factory = SAXParserFactory.newInstance(); + factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); + return factory.newSAXParser(); + } + catch (final ParserConfigurationException | SAXException e) + { + throw new OsmosisRuntimeException("Unable to create SAX Parser.", e); + } + } + /** * Creates a new instance. * @@ -66,25 +85,15 @@ public OsmosisXmlReaderFromResource(final Resource resource, final boolean enabl @Override public void run() { - InputStream inputStream = null; - try + final InputStream inputStream = this.getInputStream(); + try (Sink temporarySink = this.sink) { final SAXParser parser; - this.sink.initialize(Collections. emptyMap()); - // make "-" an alias for /dev/stdin - if (this.resource.getName() != null && this.resource.getName().equals("-")) - { - inputStream = System.in; - } - else - { - inputStream = this.resource.read(); - } - inputStream = new CompressionActivator(this.compressionMethod) - .createCompressionInputStream(inputStream); + temporarySink.initialize(Collections.emptyMap()); + parser = createParser(); parser.parse(inputStream, new OsmHandler(this.sink, this.enableDateParsing)); - this.sink.complete(); + temporarySink.complete(); } catch (final SAXParseException e) { @@ -105,18 +114,13 @@ public void run() } finally { - this.sink.release(); - if (inputStream != null) + try + { + inputStream.close(); + } + catch (final IOException e) { - try - { - inputStream.close(); - } - catch (final IOException e) - { - log.log(Level.SEVERE, "Unable to close input stream.", e); - } - inputStream = null; + log.log(Level.SEVERE, "Unable to close input stream.", e); } } } @@ -131,21 +135,24 @@ public void setSink(final Sink sink) } /** - * Creates a new SAX parser. + * Get the input stream * - * @return The newly created SAX parser. + * @return The input stream for the resource (non-null), but may throw a + * {@link OsmosisRuntimeException}. */ - private SAXParser createParser() + private InputStream getInputStream() { - try + final InputStream temporaryInputStream; + // make "-" an alias for /dev/stdin + if (this.resource.getName() != null && "-".equals(this.resource.getName())) { - final SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); - return factory.newSAXParser(); + temporaryInputStream = System.in; } - catch (final ParserConfigurationException | SAXException e) + else { - throw new OsmosisRuntimeException("Unable to create SAX Parser.", e); + temporaryInputStream = this.resource.read(); } + return new CompressionActivator(this.compressionMethod) + .createCompressionInputStream(temporaryInputStream); } } diff --git a/src/test/java/org/openstreetmap/atlas/geography/atlas/pbf/OsmosisReaderMock.java b/src/test/java/org/openstreetmap/atlas/geography/atlas/pbf/OsmosisReaderMock.java index 108f42c237..477c630eda 100644 --- a/src/test/java/org/openstreetmap/atlas/geography/atlas/pbf/OsmosisReaderMock.java +++ b/src/test/java/org/openstreetmap/atlas/geography/atlas/pbf/OsmosisReaderMock.java @@ -52,7 +52,7 @@ public void run() .forEach((identifier, relation) -> this.sink.process(new RelationContainer( new AtlasPrimitiveRelationToOsmosisRelationConverter().convert(relation)))); // Close - this.sink.release(); + this.sink.close(); this.sink.complete(); } diff --git a/src/test/java/org/openstreetmap/atlas/geography/geojson/parser/impl/jackson/GeoJsonParserJacksonImplExtensionsTest.java b/src/test/java/org/openstreetmap/atlas/geography/geojson/parser/impl/jackson/GeoJsonParserJacksonImplExtensionsTest.java index fa39f42113..4419a06213 100644 --- a/src/test/java/org/openstreetmap/atlas/geography/geojson/parser/impl/jackson/GeoJsonParserJacksonImplExtensionsTest.java +++ b/src/test/java/org/openstreetmap/atlas/geography/geojson/parser/impl/jackson/GeoJsonParserJacksonImplExtensionsTest.java @@ -1,7 +1,11 @@ package org.openstreetmap.atlas.geography.geojson.parser.impl.jackson; +import java.io.Serializable; + import org.junit.Assert; import org.junit.Test; +import org.junit.jupiter.api.Assertions; +import org.openstreetmap.atlas.geography.atlas.complete.CompleteEdge; import org.openstreetmap.atlas.geography.geojson.parser.GeoJsonParser; import org.openstreetmap.atlas.geography.geojson.parser.domain.properties.ext.change.Description; import org.openstreetmap.atlas.geography.geojson.parser.domain.properties.ext.change.Descriptor; @@ -135,6 +139,10 @@ public void featureChangeProperties() Assert.assertFalse(featureChangeProperties.getBboxWKT().isEmpty()); } + /** + * Ensure that an exception is thrown when a class that requires arguments on instantiation is + * given as an argument + */ @Test public void featureChangePropertiesBad1() { @@ -142,22 +150,18 @@ public void featureChangePropertiesBad1() final GeoJsonParser geoJsonParser = GeoJsonParserJacksonImpl.INSTANCE; - try - { - final FeatureChangeProperties featureChangeProperties = geoJsonParser - .deserializeExtension(json, FeatureChangeProperties.class); - } - catch (final Exception e) - { - final String message1 = e.getCause().getMessage(); - Assert.assertTrue(message1.startsWith("Population failed. propertyDescriptor name")); - final String message2 = e.getCause().getCause().getCause().getMessage(); - Assert.assertEquals("Can not call newInstance() on the Class for java.lang.Class", - message2); - return; - } - - Assert.fail("field name `class` should have caused a failure."); + final Exception exception = Assertions.assertThrows(Exception.class, + () -> geoJsonParser.deserializeExtension(json, + TestClassWithFieldRequiringInstantiation.class), + "field name `completeEdge` should have caused a failure."); + + final String message1 = exception.getCause().getMessage(); + Assertions.assertTrue(message1.startsWith("Population failed. propertyDescriptor name"), + message1); + final String message2 = exception.getCause().getCause().getCause().getMessage(); + Assertions.assertEquals(NoSuchMethodException.class, + exception.getCause().getCause().getCause().getClass()); + Assertions.assertEquals("java.lang.Class.()", message2); } @Test @@ -201,4 +205,22 @@ public void featureChangePropertiesRelationMemberDescriptor() Assert.assertEquals("NODE", descriptor.getItemType()); Assert.assertEquals("via", descriptor.getRole()); } + + /** + * Used exclusively for {@link #featureChangePropertiesBad1()} + */ + public static final class TestClassWithFieldRequiringInstantiation implements Serializable + { + private Class completeEdgeClass; + + public TestClassWithFieldRequiringInstantiation() + { + // Do nothing -- our mapper expects the constructor to be public + } + + public Class getCompleteEdgeClass() + { + return this.completeEdgeClass; + } + } } diff --git a/src/test/java/org/openstreetmap/atlas/utilities/checkstyle/ArrangementCheckTest.java b/src/test/java/org/openstreetmap/atlas/utilities/checkstyle/ArrangementCheckTest.java index ca891277a5..43e7072240 100644 --- a/src/test/java/org/openstreetmap/atlas/utilities/checkstyle/ArrangementCheckTest.java +++ b/src/test/java/org/openstreetmap/atlas/utilities/checkstyle/ArrangementCheckTest.java @@ -89,7 +89,7 @@ private DefaultConfiguration configuration() { final DefaultConfiguration result = createModuleConfig(ArrangementCheck.class); // Make sure to test with the configurable path! - result.addAttribute("arrangementDefinition", + result.addProperty("arrangementDefinition", ArrangementCheck.class.getResource("arrangement.txt").getPath()); return result; } diff --git a/src/test/resources/org/openstreetmap/atlas/geography/geojson/parser/featureChangePropertiesBad1.json b/src/test/resources/org/openstreetmap/atlas/geography/geojson/parser/featureChangePropertiesBad1.json index bc6b080722..7b70cd80c6 100644 --- a/src/test/resources/org/openstreetmap/atlas/geography/geojson/parser/featureChangePropertiesBad1.json +++ b/src/test/resources/org/openstreetmap/atlas/geography/geojson/parser/featureChangePropertiesBad1.json @@ -1,3 +1,3 @@ { - "class": "org.openstreetmap.atlas.geography.atlas.complete.CompleteEdge" + "completeEdgeClass": "org.openstreetmap.atlas.geography.atlas.complete.CompleteEdge" }