Initial commit - Added logic to look up world city locations via csv
All checks were successful
Locusworks Team/world-cities/pipeline/head This commit looks good

This commit is contained in:
2020-06-11 10:19:32 -05:00
commit 11a85370a9
10 changed files with 16121 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
.classpath
.project
.settings/
target/
*.pdf*
*.txt

186
Jenkinsfile vendored Normal file
View File

@ -0,0 +1,186 @@
#!groovy
// Required Jenkins plugins:
// https://wiki.jenkins-ci.org/display/JENKINS/Timestamper
// https://wiki.jenkins-ci.org/display/JENKINS/Static+Code+Analysis+Plug-ins
// https://wiki.jenkins-ci.org/display/JENKINS/Checkstyle+Plugin ?
// https://wiki.jenkins-ci.org/display/JENKINS/FindBugs+Plugin
// https://wiki.jenkins-ci.org/display/JENKINS/PMD+Plugin ?
// https://wiki.jenkins-ci.org/display/JENKINS/DRY+Plugin ?
// https://wiki.jenkins-ci.org/display/JENKINS/Task+Scanner+Plugin
// https://wiki.jenkins-ci.org/display/JENKINS/Javadoc+Plugin
// https://wiki.jenkins-ci.org/display/JENKINS/JaCoCo+Plugin ?
init()
def branch_name
def branch_name_base
def build_number
def build_url
def git_commit
def job_name
def tag
def version
def build_type
def display_name
def init() {
// Keep the 5 most recent builds
properties([[$class: 'BuildDiscarderProperty', strategy: [$class: 'LogRotator', numToKeepStr: '5']]])
build_number = env.BUILD_NUMBER
build_url = env.BUILD_URL
job_name = "${env.JOB_NAME}"
branch_name = env.BRANCH_NAME
branch_name_docker = branch_name.replaceAll(/\//,'.')
persist = "/var/lib/jenkins/PERSIST/${branch_name_docker}"
// execute the branch type specific pipeline code
try {
if (branch_name.indexOf('release/')==0) build_type='release'
if (branch_name.indexOf('feature/')==0) build_type='feature'
if (branch_name.indexOf('develop')==0) build_type='develop'
if (branch_name.indexOf('hotfix')==0) build_type='hotfix'
if (branch_name.indexOf('bugfix')==0) build_type='bugfix'
if (branch_name.indexOf('master')==0) build_type='master'
// common pipeline elements
node('master') {
Initialize()
SetVersion(build_type)
print_vars() // after SetVersion - all variables now defined
set_result('INPROGRESS')
Build() // builds database via flyway migration
}
if (branch_name.indexOf('develop')==0) {
node('master') {
Deploy();
}
} else if (branch_name.indexOf('release/')==0) {
node('master') {
Deploy();
}
}
node('master') {
set_result('SUCCESS')
}
} catch (err) {
node() {
set_result('FAILURE')
}
throw err
}
}
def Build() {
stage ('build') {
mvn "install -DskipTests=true -Dbuild.revision=${git_commit}"
step([$class: 'ArtifactArchiver', artifacts: '**/target/*.jar', fingerprint: true])
}
}
def Initialize() {
stage ('initialize') {
// get new code
checkout scm
git_commit = getSha1()
}
}
def Deploy() {
stage ('deploy') {
mvn "deploy -DskipTests=true -Dbuild.number=${build_number} -Dbuild.revision=${git_commit}"
}
}
def getSha1() {
sha1 = sh(script: 'git rev-parse HEAD', returnStdout: true).trim()
echo "sha1 is ${sha1}"
return sha1
}
def mvn(args) {
withMaven(
maven: 'maven-3.6.1',
globalMavenSettingsConfig: 'locusworks-settings'
) {
sh "mvn ${args}"
}
}
def mvn_initial(args) {
mvn(args)
}
def set_result(status) {
if ( status == 'SUCCESS' ) {
currentBuild.result = status
notify_bitbucket('SUCCESSFUL')
} else if ( status == 'FAILURE' ) {
currentBuild.result = status
notify_bitbucket('FAILED')
} else if ( status == 'INPROGRESS' ) {
notify_bitbucket('INPROGRESS')
} else {
error ("unknown status")
}
// save in persistence file for access the status page
// make sure the directory exists first
sh "mkdir -p $persist && echo $status > $persist/build.result"
}
def notify_bitbucket(state) {
}
def print_vars() {
echo "build_number = ${build_number}"
echo "build_url = ${build_url}"
echo "job_name = ${job_name}"
echo "branch_name = ${branch_name}"
echo "branch_name_base = ${branch_name_base}"
echo "build_type = ${build_type}"
echo "display_name = ${currentBuild.displayName}"
echo "version = ${version}"
echo "git_commit = ${git_commit}"
}
def SetVersion( v ) {
stage ('set version') {
echo "set version ${v}"
branch_name_base = (branch_name =~ /([^\/]+$)/)[0][0]
if ( v == 'release' ) {
// for release branches, where the branch is named "release/1.2.3",
// derive the version and display name derive from the numeric suffix and append the build number
// 3.2.1.100
version = branch_name_base + "." + build_number + "-RELEASE";
//version = branch_name.substring('release/'.length()) + "." + build_number
currentBuild.displayName = version
} else if (v == 'develop') {
version = branch_name_base + "." + build_number + "-SNAPSHOT";
currentBuild.displayName = version
} else {
// for all other branches the version number is 0 with an appended build number
// and for the display name use the jenkins default #n and add the branch name
// #101 - feature/user/foo
//version = '0.' + build_number
version = branch_name_base + "." + build_number
currentBuild.displayName = "#" + build_number + " - " + branch_name_base
}
display_name = currentBuild.displayName
mvn_initial "versions:set -DnewVersion=${version}"
}
}
return this

97
pom.xml Normal file
View File

@ -0,0 +1,97 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.locusworks</groupId>
<artifactId>world-cities</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>world-cities</name>
<description>World Cities</description>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<jackson.version>2.11.0</jackson.version>
<nexus.repo>https://nexus.locusworks.net</nexus.repo>
</properties>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>5.6.2</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-csv -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.8</version>
</dependency>
</dependencies>
<distributionManagement>
<snapshotRepository>
<id>nexus-snapshot</id>
<url>${nexus.repo}/repository/locusworks-snapshot/</url>
</snapshotRepository>
<repository>
<id>nexus-release</id>
<url>${nexus.repo}/repository/locusworks-release/</url>
</repository>
</distributionManagement>
<repositories>
<repository>
<id>locusworks-public</id>
<name>locusworks-public</name>
<url>${nexus.repo}/repository/locusworks-public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>locusworks-public</id>
<url>${nexus.repo}/repository/locusworks-public/</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
</project>

View File

@ -0,0 +1,43 @@
package net.locusworks.worldcities;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;
import net.locusworks.worldcities.csv.CityFileReader;
import net.locusworks.worldcities.entities.City;
public class WorldCities {
private static List<City> WORLD_CITY_LIST;
static {
try {
WORLD_CITY_LIST = CityFileReader.readCities();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public static City findByCityName(String cityName) {
return WORLD_CITY_LIST.stream().filter(c -> c.getCityName().equalsIgnoreCase(cityName))
.findFirst().orElse(null);
}
public static City findByCityAndCountry(String cityName, String country) {
return WORLD_CITY_LIST.stream()
.filter(c -> c.getCityName().equalsIgnoreCase(cityName))
.filter(c -> c.getCountryName().equalsIgnoreCase(country))
.findFirst().orElse(null);
}
public static List<City> findByCityNameLike(String cityName) {
return WORLD_CITY_LIST.stream().filter(c -> c.getCityName().toLowerCase()
.contains(cityName.toLowerCase())).collect(Collectors.toList());
}
public static List<City> findCitiesByCountry(String countryName) {
return WORLD_CITY_LIST.stream().filter(c -> c.getCountryName()
.equalsIgnoreCase(countryName.toLowerCase())).collect(Collectors.toList());
}
}

View File

@ -0,0 +1,52 @@
package net.locusworks.worldcities.csv;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVRecord;
import net.locusworks.worldcities.entities.City;
import net.locusworks.worldcities.entities.Location;
public class CityFileReader {
private static final String[] HEADERS = {"city","city_ascii","lat","lng","country","iso2","iso3","admin_name","capital","population","id"};
private static List<City> worldCities;
public static List<City> readCities() throws IOException {
if (worldCities != null && worldCities.size() > 0) return worldCities;
InputStream is = CityFileReader.class.getClassLoader().getResourceAsStream("worldcities.csv");
Iterable<CSVRecord> records = CSVFormat.DEFAULT
.withHeader(HEADERS)
.withFirstRecordAsHeader()
.parse(new InputStreamReader(is));
worldCities = StreamSupport.stream(records.spliterator(), false)
.map(r -> toCity(r))
.collect(Collectors.toList());
return worldCities;
}
private static City toCity(CSVRecord record) {
String city = record.get("city_ascii");
float lat = Float.valueOf(record.get("lat"));
float lng = Float.valueOf(record.get("lng"));;
String country = record.get("country");
String iso2 = record.get("iso2");
String iso3 = record.get("iso3");
long id = Long.valueOf(record.get("id"));
return new City(id, city, country, iso2, iso3, new Location(lat, lng));
}
}

View File

@ -0,0 +1,132 @@
package net.locusworks.worldcities.entities;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class City {
private long id;
private String cityName;
private String countryName;
private String iso2;
private String iso3;
private Location location;
public City(long id, String cityName, String countryName, Location location) {
this(id, cityName, countryName, null, null, location);
}
/**
* @param id
* @param cityName
* @param countryName
* @param iso2
* @param iso3
* @param location
*/
public City(long id, String cityName, String countryName, String iso2, String iso3, Location location) {
this.id = id;
this.cityName = cityName;
this.countryName = countryName;
this.iso2 = iso2;
this.iso3 = iso3;
this.location = location;
}
/**
* @return the id
*/
public long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(long id) {
this.id = id;
}
/**
* @return the cityName
*/
public String getCityName() {
return cityName;
}
/**
* @param cityName the cityName to set
*/
public void setCityName(String cityName) {
this.cityName = cityName;
}
/**
* @return the countryName
*/
public String getCountryName() {
return countryName;
}
/**
* @param countryName the countryName to set
*/
public void setCountryName(String countryName) {
this.countryName = countryName;
}
/**
* @return the iso2
*/
public String getIso2() {
return iso2;
}
/**
* @param iso2 the iso2 to set
*/
public void setIso2(String iso2) {
this.iso2 = iso2;
}
/**
* @return the iso3
*/
public String getIso3() {
return iso3;
}
/**
* @param iso3 the iso3 to set
*/
public void setIso3(String iso3) {
this.iso3 = iso3;
}
/**
* @return the location
*/
public Location getLocation() {
return location;
}
/**
* @param location the location to set
*/
public void setLocation(Location location) {
this.location = location;
}
@Override
public String toString() {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(this);
} catch (JsonProcessingException e) {
throw new IllegalArgumentException(e);
}
}
}

View File

@ -0,0 +1,41 @@
package net.locusworks.worldcities.entities;
public class Location {
private float latitude;
private float longitude;
public Location(float latitude, float longitude) {
this.latitude = latitude;
this.longitude = longitude;
}
public float getLatitude() {
return this.latitude;
}
public float getLongitude() {
return this.longitude;
}
public String toDMS() {
String lat = toDegreesMinutesAndSeconds(this.latitude);
String latCardinal = this.latitude >= 0 ? "N" : "S";
String lng = toDegreesMinutesAndSeconds(this.longitude);
String lngiCardinal = this.longitude >= 0 ? "E" : "W";
return String.format("%s%s%s%s", lat, latCardinal, lng, lngiCardinal);
}
private String toDegreesMinutesAndSeconds(float coordinate) {
float absolute = Math.abs(coordinate);
double degrees = Math.floor(absolute);
double minutesNotTruncated = (absolute - degrees) * 60;
double minutes = Math.floor(minutesNotTruncated);
double seconds = Math.floor((minutesNotTruncated - minutes) * 60);
return String.format("%2s%2s%s", (long)degrees, (long)minutes, seconds);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,20 @@
package net.locusworks.worldcities.tests;
import static org.junit.jupiter.api.Assertions.*;
import java.io.IOException;
import org.junit.jupiter.api.Test;
import net.locusworks.worldcities.csv.CityFileReader;
class CityFileReaderTest {
@Test
void testReadCities() throws IOException {
assertTrue(CityFileReader.readCities().size() > 0);
CityFileReader.readCities().forEach(c -> System.out.println(c));
}
}

View File

@ -0,0 +1,50 @@
package net.locusworks.worldcities.tests;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import org.junit.jupiter.api.Test;
import net.locusworks.worldcities.WorldCities;
import net.locusworks.worldcities.entities.City;
class WorldCitiesTest {
@Test
void testFindByCityName() {
City city = WorldCities.findByCityName("Cheremoshna");
assertNotNull(city);
assertEquals(city.getCityName(), "Cheremoshna");
}
@Test
void testFindByCityNameLike() {
List<City> cities = WorldCities.findByCityNameLike("Cher");
assertTrue(cities.size() == 33);
}
@Test
void testFindCitiesByCountry() throws IOException {
List<City> cities = WorldCities.findCitiesByCountry("Ukraine");
assertTrue(cities.size() == 51);
Path file = Paths.get("ukraine.txt");
try(BufferedWriter bos = new BufferedWriter(Files.newBufferedWriter(file))) {
for (City c : cities) {
bos.write(String.format("%s%n", c));
System.out.println(c.getLocation().toDMS());
}
}
}
}