Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
rlanning2
OpenWeather REST and file connector
Commits
6dd5dae5
Commit
6dd5dae5
authored
Oct 22, 2021
by
Christopher Bohn
🤔
Browse files
Initial commit
parents
Changes
10
Hide whitespace changes
Inline
Side-by-side
.gitignore
0 → 100644
View file @
6dd5dae5
# Mac file finder metadata
.DS_Store
# Windows file metadata
._*
# Thumbnail image caches
Thumbs.db
ethumbs.db
# MS Office temporary file
~*
# Emacs backup file
*~
# Common
[Bb]in/
[Bb]uild/
[Oo]bj/
[Oo]ut/
[Tt]mp/
[Xx]86/
[Ii][Aa]32/
[Xx]64/
[Xx]86_64/
[Xx]86-64/
[Aa]rm
[Aa]32
[Tt]32
[Aa]64
*.tmp
*.bak
*.bk
*.swp
# Java files
*.class
javadoc/
# Maven
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
# JetBrains (IntelliJ IDEA, PyCharm, etc) files
.idea/
cmake-build-*/
*.iml
*.iws
*.ipr
# Eclipse files
.settings/
.project
.classpath
.buildpath
.loadpath
.factorypath
local.properties
pom.xml
0 → 100644
View file @
6dd5dae5
<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 http://maven.apache.org/maven-v4_0_0.xsd"
>
<modelVersion>
4.0.0
</modelVersion>
<groupId>
edu.unl.cse.soft160.rest_connector
</groupId>
<artifactId>
rest_and_file_connector
</artifactId>
<packaging>
jar
</packaging>
<version>
1.0-SNAPSHOT
</version>
<name>
rest_connector
</name>
<url>
http://maven.apache.org
</url>
<properties>
<project.build.sourceEncoding>
UTF-8
</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<artifactId>
maven-compiler-plugin
</artifactId>
<version>
3.8.1
</version>
<configuration>
<source>
8
</source>
<target>
8
</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>
com.googlecode.json-simple
</groupId>
<artifactId>
json-simple
</artifactId>
<version>
1.1.1
</version>
</dependency>
<dependency>
<groupId>
junit
</groupId>
<artifactId>
junit
</artifactId>
<version>
4.13
</version>
<scope>
test
</scope>
</dependency>
<dependency>
<groupId>
org.jetbrains
</groupId>
<artifactId>
annotations
</artifactId>
<version>
RELEASE
</version>
<scope>
compile
</scope>
</dependency>
</dependencies>
</project>
src/main/java/edu/unl/cse/soft160/json_connections/Main.java
0 → 100644
View file @
6dd5dae5
package
edu.unl.cse.soft160.json_connections
;
import
edu.unl.cse.soft160.json_connections.connector.OpenWeatherConnector
;
import
org.json.simple.JSONObject
;
import
org.json.simple.parser.JSONParser
;
import
org.json.simple.parser.ParseException
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
java.util.Objects
;
public
class
Main
{
private
static
String
getApiKey
()
{
JSONObject
apiKeyJson
=
null
;
String
filename
=
"apikey.json"
;
try
(
InputStreamReader
inputStreamReader
=
new
InputStreamReader
(
Objects
.
requireNonNull
(
Main
.
class
.
getClassLoader
().
getResourceAsStream
(
filename
))))
{
apiKeyJson
=
(
JSONObject
)
new
JSONParser
().
parse
(
inputStreamReader
);
}
catch
(
NullPointerException
nullPointerException
)
{
System
.
err
.
println
(
"Could not find "
+
filename
+
". Terminating."
);
System
.
exit
(
1
);
}
catch
(
IOException
ioException
)
{
System
.
err
.
println
(
"Error loading "
+
filename
+
". Terminating."
);
System
.
exit
(
1
);
}
catch
(
ParseException
parseException
)
{
System
.
err
.
println
(
"Parse exception encountered while parsing "
+
filename
+
". Terminating."
);
System
.
exit
(
1
);
}
return
apiKeyJson
.
get
(
"apikey"
).
toString
();
}
public
static
void
main
(
String
...
args
)
{
String
apiKey
=
getApiKey
();
OpenWeatherConnector
weather
=
new
OpenWeatherConnector
(
"weather"
,
apiKey
);
String
data
=
null
;
try
{
data
=
weather
.
retrieveData
(
"zip=68588"
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
System
.
out
.
println
(
data
);
System
.
out
.
println
(
weather
.
getWeatherCategory
());
System
.
out
.
println
(
"Temperature: "
+
weather
.
getTemperature
()
+
"K"
);
System
.
out
.
println
(
"Cloud cover: "
+
weather
.
getCloudCover
()
+
"%"
);
System
.
out
.
println
(
"Timestamp: "
+
weather
.
getTimestamp
());
}
}
src/main/java/edu/unl/cse/soft160/json_connections/connection/Connection.java
0 → 100644
View file @
6dd5dae5
package
edu.unl.cse.soft160.json_connections.connection
;
import
org.json.simple.JSONObject
;
import
org.json.simple.parser.ParseException
;
import
java.io.IOException
;
public
interface
Connection
{
JSONObject
get
(
String
filename
)
throws
IOException
,
ParseException
;
}
src/main/java/edu/unl/cse/soft160/json_connections/connection/FileConnection.java
0 → 100644
View file @
6dd5dae5
package
edu.unl.cse.soft160.json_connections.connection
;
import
org.json.simple.JSONObject
;
import
org.json.simple.parser.JSONParser
;
import
org.json.simple.parser.ParseException
;
import
java.io.FileWriter
;
import
java.io.IOException
;
import
java.io.InputStreamReader
;
import
java.util.Objects
;
public
class
FileConnection
implements
Connection
{
String
directory
;
public
FileConnection
()
{
directory
=
""
;
}
public
FileConnection
(
String
directory
)
{
this
.
directory
=
directory
+
"/"
;
}
public
JSONObject
get
(
String
filename
)
throws
IOException
,
ParseException
{
JSONObject
data
;
try
(
InputStreamReader
inputStreamReader
=
new
InputStreamReader
(
Objects
.
requireNonNull
(
FileConnection
.
class
.
getClassLoader
().
getResourceAsStream
(
directory
+
filename
))))
{
data
=
(
JSONObject
)
new
JSONParser
().
parse
(
inputStreamReader
);
}
catch
(
NullPointerException
originalException
)
{
throw
new
IOException
(
"Could not find "
+
filename
+
"."
,
originalException
);
}
return
data
;
}
public
void
save
(
String
filename
,
JSONObject
data
)
throws
IOException
{
FileWriter
fileWriter
=
new
FileWriter
(
filename
);
data
.
writeJSONString
(
fileWriter
);
fileWriter
.
close
();
}
}
src/main/java/edu/unl/cse/soft160/json_connections/connection/RestConnection.java
0 → 100644
View file @
6dd5dae5
package
edu.unl.cse.soft160.json_connections.connection
;
import
org.json.simple.JSONObject
;
import
org.json.simple.parser.JSONParser
;
import
org.json.simple.parser.ParseException
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.InputStreamReader
;
import
java.net.MalformedURLException
;
import
java.net.URI
;
import
java.net.URISyntaxException
;
import
java.net.URLConnection
;
public
class
RestConnection
implements
Connection
{
protected
final
String
protocol
;
protected
final
String
authority
;
protected
final
String
path
;
protected
final
String
apiKey
;
public
RestConnection
(
String
protocol
,
String
authority
,
String
path
,
String
apiKey
)
{
this
.
protocol
=
protocol
;
this
.
authority
=
authority
;
this
.
path
=
path
;
this
.
apiKey
=
apiKey
;
}
public
JSONObject
get
(
String
query
)
throws
IOException
,
ParseException
{
JSONObject
data
;
try
{
URLConnection
connection
=
new
URI
(
protocol
,
authority
,
path
,
query
+
"&appid="
+
apiKey
,
null
).
toURL
().
openConnection
();
// connection.setRequestProperty("Accept", "application/json");
InputStreamReader
inputStreamReader
=
new
InputStreamReader
(
connection
.
getInputStream
());
data
=
(
JSONObject
)
new
JSONParser
().
parse
(
inputStreamReader
);
}
catch
(
URISyntaxException
|
MalformedURLException
originalException
)
{
throw
new
IOException
(
"Could not retrieve usable data from "
+
authority
+
"."
,
originalException
);
}
return
data
;
}
}
src/main/java/edu/unl/cse/soft160/json_connections/connector/OpenWeatherConnector.java
0 → 100644
View file @
6dd5dae5
package
edu.unl.cse.soft160.json_connections.connector
;
import
edu.unl.cse.soft160.json_connections.connection.Connection
;
import
edu.unl.cse.soft160.json_connections.connection.FileConnection
;
import
edu.unl.cse.soft160.json_connections.connection.RestConnection
;
import
org.json.simple.JSONArray
;
import
org.json.simple.JSONObject
;
import
org.json.simple.parser.ParseException
;
import
java.io.FileNotFoundException
;
import
java.io.IOException
;
import
java.util.ArrayList
;
import
java.util.Date
;
import
java.util.List
;
public
class
OpenWeatherConnector
{
public
enum
WeatherCategory
{
THUNDERSTORM
,
DRIZZLE
,
RAIN
,
SNOW
,
ATMOSPHERE
,
CLEAR
,
CLOUDS
,
UNKNOWN_CATEGORY
,
}
protected
enum
DataSet
{
WEATHER
,
ONECALL
,
FORECAST
,
AIR_POLLUTION
,
DIRECT
,
STATIONS
,
// TRIGGERS, // triggers is a POST call
}
protected
static
final
String
PROTOCOL
=
"http"
;
protected
static
final
String
REST_AUTHORITY
=
"api.openweathermap.org"
;
protected
static
String
REST_PATH
;
// Should be able to declare this as final, but static analysis doesn't see that
protected
final
Connection
dataSource
;
protected
final
DataSet
dataSet
;
protected
JSONObject
data
;
public
OpenWeatherConnector
(
String
fileDataSet
)
{
dataSource
=
new
FileConnection
(
fileDataSet
);
dataSet
=
DataSet
.
valueOf
(
fileDataSet
.
toUpperCase
());
data
=
null
;
switch
(
dataSet
)
{
case
WEATHER:
case
ONECALL:
case
FORECAST:
case
AIR_POLLUTION:
REST_PATH
=
"/data/2.5"
;
break
;
case
DIRECT:
REST_PATH
=
"geo/1.0"
;
break
;
case
STATIONS:
// case TRIGGERS:
REST_PATH
=
"data/3.0"
;
break
;
default
:
REST_PATH
=
"unknown"
;
}
}
public
OpenWeatherConnector
(
String
restDataSet
,
String
apiKey
)
{
dataSource
=
new
RestConnection
(
PROTOCOL
,
REST_AUTHORITY
,
REST_PATH
+
restDataSet
,
apiKey
);
dataSet
=
DataSet
.
valueOf
(
restDataSet
.
toUpperCase
());
data
=
null
;
switch
(
dataSet
)
{
case
WEATHER:
case
ONECALL:
case
FORECAST:
case
AIR_POLLUTION:
REST_PATH
=
"/data/2.5"
;
break
;
case
DIRECT:
REST_PATH
=
"geo/1.0"
;
break
;
case
STATIONS:
// case TRIGGERS:
REST_PATH
=
"data/3.0"
;
break
;
default
:
REST_PATH
=
"unknown"
;
}
}
public
String
retrieveData
(
String
requestedData
)
throws
IOException
{
try
{
data
=
dataSource
.
get
(
requestedData
);
}
catch
(
FileNotFoundException
fileNotFoundException
)
{
if
(
dataSource
instanceof
RestConnection
)
{
throw
new
IOException
(
"Could not access \""
+
dataSet
.
toString
().
toLowerCase
()
+
"\" dataset at "
+
REST_AUTHORITY
+
"."
,
fileNotFoundException
);
}
else
{
throw
fileNotFoundException
;
// For FileConnection, this exception is exactly what's on the label,
}
// except that we'd more likely see a...
}
catch
(
NullPointerException
nullPointerException
)
{
if
(
dataSource
instanceof
FileConnection
)
{
FileNotFoundException
newException
=
new
FileNotFoundException
(
"File "
+
requestedData
+
" not found."
);
newException
.
initCause
(
nullPointerException
);
throw
newException
;
}
else
{
throw
nullPointerException
;
// Not going to try to predict why RestConnection generates NPE
}
}
catch
(
ParseException
parseException
)
{
String
message
;
if
(
dataSource
instanceof
FileConnection
)
{
message
=
"Error while parsing file "
+
requestedData
+
"."
;
}
else
if
(
dataSource
instanceof
RestConnection
)
{
message
=
"Error while parsing the "
+
dataSet
.
toString
().
toLowerCase
()
+
" response from "
+
REST_AUTHORITY
+
"."
;
}
else
{
message
=
"Error while parsing requested data."
;
}
throw
new
IOException
(
message
,
parseException
);
}
return
data
.
toJSONString
();
}
private
void
checkForDataPresence
()
{
if
(
data
==
null
)
{
throw
new
IllegalStateException
(
"No data has been retrieved from the "
+
dataSet
.
toString
().
toLowerCase
()
+
"dataset."
);
}
}
private
double
retrieveDoubleValue
(
String
field
,
double
defaultValue
)
{
checkForDataPresence
();
double
returnValue
=
defaultValue
;
if
(
data
.
containsKey
(
field
))
{
Double
value
=
(
Double
)
data
.
get
(
field
);
returnValue
=
value
==
null
?
defaultValue
:
value
;
}
return
returnValue
;
}
private
double
retrieveDoubleValue
(
String
topLevelField
,
String
subField
,
double
defaultValue
)
{
checkForDataPresence
();
double
returnValue
=
defaultValue
;
if
(
data
.
containsKey
(
topLevelField
))
{
JSONObject
observations
=
(
JSONObject
)
data
.
get
(
topLevelField
);
if
(
data
.
containsKey
(
subField
))
{
Double
value
=
(
Double
)
observations
.
get
(
subField
);
returnValue
=
value
==
null
?
defaultValue
:
value
;
}
}
return
returnValue
;
}
private
long
retrieveLongValue
(
String
field
,
long
defaultValue
)
{
checkForDataPresence
();
long
returnValue
=
defaultValue
;
if
(
data
.
containsKey
(
field
))
{
Long
value
=
(
Long
)
data
.
get
(
field
);
returnValue
=
value
==
null
?
defaultValue
:
value
;
}
return
returnValue
;
}
private
long
retrieveLongValue
(
String
topLevelField
,
String
subField
,
long
defaultValue
)
{
checkForDataPresence
();
long
returnValue
=
defaultValue
;
if
(
data
.
containsKey
(
topLevelField
))
{
JSONObject
observations
=
(
JSONObject
)
data
.
get
(
topLevelField
);
if
(
data
.
containsKey
(
subField
))
{
Long
value
=
(
Long
)
observations
.
get
(
subField
);
returnValue
=
value
==
null
?
defaultValue
:
value
;
}
}
return
returnValue
;
}
/* For now, we're only working with the current "weather" dataSet.
* We probably want to add "onecall" "forecast" "air_pollution"
* Not "map" since that doesn't look to be a download, and certainly not JSON
*/
public
double
getLatitude
()
{
return
retrieveDoubleValue
(
"coord"
,
"lat"
,
Double
.
NaN
);
}
public
double
getLongitude
()
{
return
retrieveDoubleValue
(
"coord"
,
"long"
,
Double
.
NaN
);
}
public
Date
getTimestamp
()
{
long
unixTime
=
retrieveLongValue
(
"dt"
,
Long
.
MIN_VALUE
);
return
new
Date
(
unixTime
*
1000
);
}
public
List
<
WeatherCategory
>
getWeatherCategory
()
{
checkForDataPresence
();
JSONArray
weather
=
(
JSONArray
)
data
.
get
(
"weather"
);
List
<
WeatherCategory
>
categories
=
new
ArrayList
<>(
weather
.
size
());
for
(
Object
condition
:
weather
)
{
String
category
=
((
JSONObject
)
condition
).
get
(
"main"
).
toString
();
try
{
categories
.
add
(
WeatherCategory
.
valueOf
(
category
.
toUpperCase
()));
}
catch
(
IllegalArgumentException
ignored
)
{
categories
.
add
(
WeatherCategory
.
UNKNOWN_CATEGORY
);
}
}
return
categories
;
}
public
List
<
String
>
getWeatherDescriptions
()
{
checkForDataPresence
();
JSONArray
weather
=
(
JSONArray
)
data
.
get
(
"weather"
);
List
<
String
>
categories
=
new
ArrayList
<>(
weather
.
size
());
for
(
Object
condition
:
weather
)
{
categories
.
add
(((
JSONObject
)
condition
).
get
(
"description"
).
toString
());
}
return
categories
;
}
public
long
getVisibility
()
{
return
retrieveLongValue
(
"visibility"
,
Long
.
MIN_VALUE
);
}
public
double
getTemperature
()
{
return
retrieveDoubleValue
(
"main"
,
"temp"
,
Double
.
NaN
);
}
public
long
getHumidity
()
{
return
retrieveLongValue
(
"main"
,
"humidity"
,
Long
.
MIN_VALUE
);
}
public
double
getFeelsLike
()
{
return
retrieveDoubleValue
(
"main"
,
"feels_like"
,
Double
.
NaN
);
}
public
long
getPressure
()
{
return
retrieveLongValue
(
"main"
,
"pressure"
,
Long
.
MIN_VALUE
);
}
public
long
getWindDirection
()
{
return
retrieveLongValue
(
"wind"
,
"deg"
,
Long
.
MIN_VALUE
);
}
public
double
getWindSpeed
()
{
return
retrieveDoubleValue
(
"wind"
,
"speed"
,
0.0
);
}
public
double
getWindGust
()
{
checkForDataPresence
();
if
(
data
.
containsKey
(
"wind"
))
{
JSONObject
wind
=
(
JSONObject
)
data
.
get
(
"wind"
);
return
retrieveDoubleValue
(
"gust"
,
getWindSpeed
());
}
else
{
return
0.0
;
}
}
public
long
getCloudCover
()
{
return
retrieveLongValue
(
"clouds"
,
"all"
,
0
);
}
public
double
getOneHourRainfall
()
{
return
retrieveDoubleValue
(
"rain"
,
"1h"
,
0.0
);
}
public
double
getThreeHourRainfall
()
{
return
retrieveDoubleValue
(
"rain"
,
"3h"
,
0.0
);
}
public
double
getOneHourSnowfall
()
{
return
retrieveDoubleValue
(
"snow"
,
"1h"
,
0.0
);
}
public
double
getThreeHourSnowfall
()
{
return
retrieveDoubleValue
(
"snow"
,
"3h"
,
0.0
);
}
}
src/main/resources/.gitignore
0 → 100644
View file @
6dd5dae5
apikey.json
src/main/resources/apikey.json-TEMPLATE
0 → 100644
View file @
6dd5dae5
{
"apikey": ""
}
src/main/resources/weather/sample.json
0 → 100644
View file @
6dd5dae5
{
"visibility"
:
10000
,
"timezone"
:
-18000
,
"main"
:
{
"temp"
:
281.8
,
"temp_min"
:
279.77
,
"humidity"
:
73
,
"pressure"
:
1023
,
"feels_like"
:
281.45
,
"temp_max"
:
283.4
},
"clouds"
:
{
"all"
:
34
},
"sys"
:
{
"country"
:
"US"
,
"sunrise"
:
1634820289
,
"sunset"
:
1634859453
,
"id"
:
2039228
,
"type"
:
2
},
"dt"
:
1634835577
,
"coord"
:
{
"lon"
:
-96.6928
,
"lat"
:
40.8206
},
"weather"
:
[
{
"icon"
:
"03d"
,
"description"
:
"scattered clouds"
,
"main"
:
"Clouds"
,
"id"
:
802
}
],
"name"
:
"Lincoln"
,
"cod"
:
200
,
"id"
:
0
,
"base"
:
"stations"
,
"wind"
:
{
"deg"
:
41
,
"speed"
:
1.34
,
"gust"
:
3.13
}
}
\ No newline at end of file
Write
Preview
Supports
Markdown