Initial commit
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Gradle build configuration for specific lab module / exercise
|
||||
*/
|
||||
// enabled plugins
|
||||
plugins {
|
||||
id 'java'
|
||||
// Apply the application plugin to add support for building a CLI application.
|
||||
id 'application'
|
||||
}
|
||||
|
||||
// Project/Module information
|
||||
description = 'Lab05 ByteCharStream'
|
||||
group = 'ch.zhaw.prog2'
|
||||
version = '2022.1'
|
||||
|
||||
// Dependency configuration
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
}
|
||||
|
||||
// Configuration for Application plugin
|
||||
application {
|
||||
// Define the main class for the application.
|
||||
mainClass = 'ch.zhaw.prog2.io.FileCopy'
|
||||
}
|
||||
|
||||
// enable console input when running with gradle
|
||||
run {
|
||||
standardInput = System.in
|
||||
}
|
||||
|
||||
|
||||
// Java plugin configuration
|
||||
java {
|
||||
// By default the Java version of the gradle process is used as source/target version.
|
||||
// This can be overridden, to ensure a specific version. Enable only if required.
|
||||
// sourceCompatibility = JavaVersion.VERSION_17 // ensure Java source code compatibility
|
||||
// targetCompatibility = JavaVersion.VERSION_17 // version of the created byte-code
|
||||
|
||||
// Java compiler specific options
|
||||
compileJava {
|
||||
// source files should be UTF-8 encoded
|
||||
options.encoding = 'UTF-8'
|
||||
// for more options see https://docs.gradle.org/current/dsl/org.gradle.api.tasks.compile.CompileOptions.html
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
ENGINE
|
||||
Engine 449cc, 4-stroke, liquid-cooled, single cylinder, DOHC
|
||||
Bore Stroke 96.0 x 62.1 mm (3.78 x 2.4 in)
|
||||
Compression Ratio 12.5:1
|
||||
Fuel System Fuel Injection
|
||||
Starter Primary kick
|
||||
Lubrication Semi-dry sump
|
||||
DRIVE TRAIN
|
||||
Transmission 5-speed constant mesh
|
||||
Clutch Wet multi-plate type, manual release
|
||||
Final Drive Chain, DID520MXV4, 114 links
|
||||
CHASSIS
|
||||
Suspension Front Inverted telescopic, air spring, oil damped
|
||||
Suspension Rear Link type, coil spring, oil damped
|
||||
Brakes Front Disc brake, single rotor
|
||||
Brakes Rear Disc brake, single rotor
|
||||
Tires Front 80/100-21 51M, tube type
|
||||
Tires Rear 110/90-19 62M, tube type
|
||||
Fuel Tank Capacity 6.2 L (1.6 US gallons)
|
||||
Color Champion Yellow No.2 / Solid Black
|
||||
ELECTRICAL
|
||||
Ignition Electronic Ignition (CDI)
|
||||
DIMENSIONS
|
||||
Overall Length 2190 mm (86.2 in)
|
||||
Overall Width 830 mm (32.7 in)
|
||||
Overall Height 1270 mm (50.0 in)
|
||||
Wheelbase 1495 mm (58.9 in)
|
||||
Ground Clearance 325 mm (12.8 in)
|
||||
Seat Height 955 mm (37.6 in)
|
||||
Curb Weight 112 kg (247 lbs)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 134 KiB |
@@ -0,0 +1,71 @@
|
||||
package ch.zhaw.prog2.io;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
public class FileCopy {
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
// get the filename from the arguments. By default, use 'files'-directory in current working directory.
|
||||
String sourceDirPath = args.length >= 1 ? args[0] : "./files";
|
||||
File sourceDir = new File(sourceDirPath);
|
||||
|
||||
// Part a – Verify the directory structure
|
||||
// Implement the method 'verifySourceDir()'
|
||||
System.out.format("Verifying Source Directory: %s%n", sourceDirPath);
|
||||
try {
|
||||
verifySourceDir(sourceDir);
|
||||
} catch (FileNotFoundException error) {
|
||||
System.err.format("Directory %s does not comply with predefined structure: %s%n", sourceDir.getPath(), error.getMessage());
|
||||
System.err.println("Terminating programm!");
|
||||
System.exit(1);
|
||||
}
|
||||
System.out.printf("Source Directory verified successfully.");
|
||||
|
||||
|
||||
// Part b – Copy the files byte resp. char wise.
|
||||
// Implement the method 'verifySourceDir()'
|
||||
System.out.println("Initiating file copies.");
|
||||
try {
|
||||
copyFiles(sourceDir);
|
||||
} catch (IOException error) {
|
||||
System.err.format("Error creating file copies: %s%n", error.getMessage());
|
||||
System.err.println("Terminating programm!");
|
||||
System.exit(2);
|
||||
}
|
||||
System.out.println("Files copied successfully.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Part a – directory structure
|
||||
*
|
||||
* Verify the directory structure for correctness.
|
||||
* Correct means, that the directory exists and beside the two files rmz450.jpg and rmz450-spec.txt does not contain
|
||||
* any other files or directories.
|
||||
*
|
||||
* @param sourceDir File source directory to verify it contains the correct structure
|
||||
* @throws FileNotFoundException if the source directory or required file are missing
|
||||
* @throws InvalidObjectException if the source directory contains invalid files or directories.
|
||||
*/
|
||||
private static void verifySourceDir(File sourceDir) throws FileNotFoundException, InvalidObjectException {
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Teilaufgabe b – Kopieren von Dateien
|
||||
*
|
||||
* Copies each file of the source directory twice, once character-oriented and once byte-oriented.
|
||||
* Source and target files should be opened and copied byte by byte respectively char by char.
|
||||
* The target files should be named, so the type of copy can be identified.
|
||||
*
|
||||
* @param sourceDir File representing the source directory containing the files to copy
|
||||
* @throws IOException if an error is happening while copying the files
|
||||
*/
|
||||
private static void copyFiles(File sourceDir) throws IOException {
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Gradle build configuration for specific lab module / exercise
|
||||
*/
|
||||
// enabled plugins
|
||||
plugins {
|
||||
id 'java'
|
||||
// Apply the application plugin to add support for building a CLI application.
|
||||
id 'application'
|
||||
}
|
||||
|
||||
// Project/Module information
|
||||
description = 'Lab05 UnderstandingCharsets'
|
||||
group = 'ch.zhaw.prog2'
|
||||
version = '2022.1'
|
||||
|
||||
// Dependency configuration
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
}
|
||||
|
||||
// Configuration for Application plugin
|
||||
application {
|
||||
// Define the main class for the application.
|
||||
mainClass = 'ch.zhaw.prog2.io.UnderstandingCharsets'
|
||||
}
|
||||
|
||||
// enable console input when running with gradle
|
||||
run {
|
||||
standardInput = System.in
|
||||
}
|
||||
|
||||
|
||||
// Java plugin configuration
|
||||
java {
|
||||
// By default the Java version of the gradle process is used as source/target version.
|
||||
// This can be overridden, to ensure a specific version. Enable only if required.
|
||||
// sourceCompatibility = JavaVersion.VERSION_17 // ensure Java source code compatibility
|
||||
// targetCompatibility = JavaVersion.VERSION_17 // version of the created byte-code
|
||||
|
||||
// Java compiler specific options
|
||||
compileJava {
|
||||
// source files should be UTF-8 encoded
|
||||
options.encoding = 'UTF-8'
|
||||
// for more options see https://docs.gradle.org/current/dsl/org.gradle.api.tasks.compile.CompileOptions.html
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package ch.zhaw.prog2.io;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
|
||||
public class UnderstandingCharsets {
|
||||
public static void main(String[] args) {
|
||||
|
||||
|
||||
/* Teilaufgabe a
|
||||
* In der Vorlesung haben Sie gelernt, dass Java-Klassen fuer Unicode entworfen wurden.
|
||||
* Nun ist Unicode aber nicht der einzige Zeichensatz und Java unterstuetz durchaus Alternativen.
|
||||
* Welche Zeichensaetze auf einem System konkret unterstuetzt werden haengt von der Konfiguration des Betriebssystems JVM ab.
|
||||
* Schreiben Sie ein Programm, welches alle Unterstuetzten Zeichensaetze auf der Konsole (System.out) ausgibt,
|
||||
* zusammen mit dem Standardzeichensatz.
|
||||
* https://docs.oracle.com/javase/8/docs/api/java/nio/charset/Charset.html
|
||||
*/
|
||||
|
||||
// ToDo: Print default character set
|
||||
|
||||
|
||||
// Todo: Print all available character sets
|
||||
|
||||
|
||||
|
||||
/* Ende Teilaufgabe a */
|
||||
|
||||
|
||||
/* Teilaufgabe b
|
||||
* Ergänzen Sie die Klasse so, dass sie einzelne Zeichen (also Zeichen für Zeichen) im Standardzeichensatz
|
||||
* von der Konsole einliest und in zwei Dateien schreibt einmal im Standardzeichensatz und einmal im
|
||||
* Zeichensatz `US-ASCII`.
|
||||
* Die Eingabe des Zeichens `q` soll das Program ordentlich beenden.
|
||||
* Die Dateien sollen `CharSetEvaluation_Default.txt` und `CharSetEvaluation_ASCII.txt` genannt und
|
||||
* werden entweder erzeugt oder, falls sie bereits existieren, geöffnet und der Inhalt überschrieben.
|
||||
* Testen Sie Ihr Program mit den folgenden Zeichen: a B c d € f ü _ q
|
||||
* Öffnen Sie die Textdateien nach Ausführung des Programs mit einem Texteditor und erklären Sie das Ergebnis.
|
||||
* Öffnen Sie die Dateien anschliessend mit einem HEX-Editor und vergleichen Sie.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Gradle build configuration for specific lab module / exercise
|
||||
*/
|
||||
// enabled plugins
|
||||
plugins {
|
||||
id 'java'
|
||||
// Apply the application plugin to add support for building a CLI application.
|
||||
id 'application'
|
||||
}
|
||||
|
||||
// Project/Module information
|
||||
description = 'Lab05 FileAttributes'
|
||||
group = 'ch.zhaw.prog2'
|
||||
version = '2022.1'
|
||||
|
||||
// Dependency configuration
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
||||
}
|
||||
|
||||
// Configuration for Application plugin
|
||||
application {
|
||||
// Define the main class for the application.
|
||||
mainClass = 'ch.zhaw.prog2.io.DirList'
|
||||
}
|
||||
|
||||
// enable console input when running with gradle
|
||||
run {
|
||||
standardInput = System.in
|
||||
}
|
||||
|
||||
|
||||
// Java plugin configuration
|
||||
java {
|
||||
// By default the Java version of the gradle process is used as source/target version.
|
||||
// This can be overridden, to ensure a specific version. Enable only if required.
|
||||
// sourceCompatibility = JavaVersion.VERSION_17 // ensure Java source code compatibility
|
||||
// targetCompatibility = JavaVersion.VERSION_17 // version of the created byte-code
|
||||
|
||||
// Java compiler specific options
|
||||
compileJava {
|
||||
// source files should be UTF-8 encoded
|
||||
options.encoding = 'UTF-8'
|
||||
// for more options see https://docs.gradle.org/current/dsl/org.gradle.api.tasks.compile.CompileOptions.html
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package ch.zhaw.prog2.io;
|
||||
|
||||
import java.io.File;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
public class DirList {
|
||||
private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
|
||||
public static void main(String[] args) {
|
||||
String pathName = args.length >= 1 ? args[0] : ".";
|
||||
File file = new File(pathName);
|
||||
// Write metadata of given file, resp. all of its files if it is a directory
|
||||
// Whith each file on one line in the following format.
|
||||
// - type of file ('d'=directory, 'f'=file)
|
||||
// - readable 'r', '-' otherwise
|
||||
// - writable 'w', '-' otherwise
|
||||
// - executable 'x', '-' otherwise
|
||||
// - hidden 'h', '-' otherwise
|
||||
// - modified date in format 'yyyy-MM-dd HH:mm:ss'
|
||||
// - length in bytes
|
||||
// - name of the file
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Gradle build configuration for specific lab module / exercise
|
||||
*/
|
||||
// enabled plugins
|
||||
plugins {
|
||||
id 'java'
|
||||
// Apply the application plugin to add support for building a CLI application.
|
||||
id 'application'
|
||||
}
|
||||
|
||||
// Project/Module information
|
||||
description = 'Lab05 PictureDB'
|
||||
group = 'ch.zhaw.prog2'
|
||||
version = '2022.1'
|
||||
|
||||
// Dependency configuration
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
// Junit 5 dependencies
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.+'
|
||||
testImplementation 'org.junit.jupiter:junit-jupiter-params:5.8.+'
|
||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.+'
|
||||
}
|
||||
|
||||
// Test task configuration
|
||||
test {
|
||||
// Use JUnit platform for unit tests
|
||||
useJUnitPlatform()
|
||||
// Output results of individual tests
|
||||
testLogging {
|
||||
events "PASSED", "SKIPPED", "FAILED"
|
||||
}
|
||||
}
|
||||
|
||||
// Configuration for Application plugin
|
||||
application {
|
||||
// Define the main class for the application.
|
||||
mainClass = 'ch.zhaw.prog2.io.picturedb.PictureImport'
|
||||
}
|
||||
|
||||
// Run task configuration
|
||||
run {
|
||||
// enable console input when running with gradle
|
||||
standardInput = System.in
|
||||
// set system property to load log configuration using class (takes precedence; if not set or fails, file is used)
|
||||
systemProperty 'java.util.logging.config.class', 'ch.zhaw.prog2.io.picturedb.LogConfiguration'
|
||||
// set system property to load log configuration from properties
|
||||
systemProperty 'java.util.logging.config.file', 'log.properties'
|
||||
}
|
||||
|
||||
|
||||
// Java plugin configuration
|
||||
java {
|
||||
// By default the Java version of the gradle process is used as source/target version.
|
||||
// This can be overridden, to ensure a specific version. Enable only if required.
|
||||
// sourceCompatibility = JavaVersion.VERSION_17 // ensure Java source code compatibility
|
||||
// targetCompatibility = JavaVersion.VERSION_17 // version of the created byte-code
|
||||
|
||||
// Java compiler specific options
|
||||
compileJava {
|
||||
// source files should be UTF-8 encoded
|
||||
options.encoding = 'UTF-8'
|
||||
// for more options see https://docs.gradle.org/current/dsl/org.gradle.api.tasks.compile.CompileOptions.html
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
1;2014-03-17 14:30:05;2.324744;48.864506;Another Monkey;http://www.codemonkey.in/images/Code-Monkey.png
|
||||
13;2014-04-01 02:17:33;77.598736;12.979842;Bête à coder;http://www2.craven.fr/blojsom/resources/default/codemonkey.jpg
|
||||
14;2013-05-07 13:45:13;-71.098270;42.302583;Need a coder;http://blog.stackoverflow.com/wp-content/uploads/code_monkey_colour.jpg
|
||||
|
@@ -0,0 +1,42 @@
|
||||
## Console handler configuration
|
||||
java.util.logging.ConsoleHandler.level = ALL
|
||||
|
||||
## File handler configuration
|
||||
## see https://docs.oracle.com/en/java/javase/11/docs/api/java.logging/java/util/logging/FileHandler.html
|
||||
java.util.logging.FileHandler.level = ALL
|
||||
# %g = generation number, %u = unique number to resolve conflicts
|
||||
java.util.logging.FileHandler.pattern = log-%g-%u.log
|
||||
# use SimpleFormatter instead of default XMLFormatter
|
||||
java.util.logging.FileHandler.formatter = java.util.logging.SimpleFormatter
|
||||
java.util.logging.FileHandler.encoding = UTF-8
|
||||
# max log file size in byte before switching to next generation (=10`kB); 0=unlimited
|
||||
java.util.logging.FileHandler.limit = 10240
|
||||
# max number of generations (%g) before overwriting (5 -> 0..4)
|
||||
java.util.logging.FileHandler.count=5
|
||||
java.util.logging.FileHandler.append=true
|
||||
|
||||
## Configure format of log messages
|
||||
# arguments see https://docs.oracle.com/en/java/javase/17/docs/api/java.logging/java/util/logging/SimpleFormatter.html
|
||||
# formats see https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Formatter.html
|
||||
# format "[date] [level] message exception"
|
||||
java.util.logging.SimpleFormatter.format = [%1$tF %1$tT %1tZ] [%4$s] %5$s%6$s%n
|
||||
# format "[date] [level] [logger] message exception"
|
||||
#java.util.logging.SimpleFormatter.format = [%1$tF %1$tT %1tZ] [%4$-7s] [%3$s] %5$s%6$s%n
|
||||
# format "[date] [level] [position in source] message exception"
|
||||
#java.util.logging.SimpleFormatter.format = [%1$tF %1$tT %1tZ] [%4$-7s] [%2$s] %5$s%6$s%n
|
||||
|
||||
## configure default log level (for all loggers, if not overwritten below)
|
||||
.level = INFO
|
||||
|
||||
## configure root logger ""
|
||||
handlers = java.util.logging.ConsoleHandler
|
||||
level = INFO
|
||||
|
||||
## Application specific logger configuration
|
||||
# loggers starting with "ch.zhaw.prog2.io.picturedb" -> use console and file handler
|
||||
ch.zhaw.prog2.io.picturedb.handlers = java.util.logging.FileHandler, java.util.logging.ConsoleHandler
|
||||
# do not forward to parent handlers
|
||||
ch.zhaw.prog2.io.picturedb.useParentHandlers = false
|
||||
# Set log levels for specific packages/classes
|
||||
ch.zhaw.prog2.io.picturedb.level = INFO
|
||||
#ch.zhaw.prog2.io.picturedb.FilePictureDatasource.level = FINER
|
||||
@@ -0,0 +1,67 @@
|
||||
package ch.zhaw.prog2.io.picturedb;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Generic data source interface to persist items of type T extending {@link Record}
|
||||
* What kind of persistence media is used, is defined by the concrete implementation.
|
||||
* e.g. InMemory, Files, Database, ...
|
||||
* The datatype T to be persisted, must extend {@link Record} which contains the id field to uniquely identify the record.
|
||||
*
|
||||
* @param <T extends Record> data type to persist
|
||||
*/
|
||||
public interface Datasource<T extends Record> {
|
||||
/**
|
||||
* Insert a new record to the data source.
|
||||
* The id field of the record is ignored, and a new unique id has to be generated, which will be set in the record.
|
||||
* This id is used to identify the record in the dataset by the other methods (i.e. find, update or delete methods)
|
||||
*
|
||||
* @param record of type T to insert into the data set.
|
||||
*/
|
||||
void insert(T record);
|
||||
|
||||
/**
|
||||
* Update the content of an existing record in the data set, which is identified by the unique identifier,
|
||||
* with the new values from the given record object.
|
||||
* If the identifier can not be found in the data set, an {@link RecordNotFoundException} is thrown.
|
||||
*
|
||||
* @param record to be updated in the dataset
|
||||
* @throws RecordNotFoundException if the record is not existing
|
||||
*/
|
||||
void update(T record) throws RecordNotFoundException;
|
||||
|
||||
/**
|
||||
* Deletes the record, identified by the id of the given record from the data set.
|
||||
* All other fields of the record are ignored.
|
||||
* If the identifier can not be found in the data set, an {@link RecordNotFoundException} is thrown.
|
||||
*
|
||||
* @param record to be deleted
|
||||
* @throws RecordNotFoundException if the record is not existing
|
||||
*/
|
||||
void delete(T record) throws RecordNotFoundException;
|
||||
|
||||
/**
|
||||
* Returns the number of records in the data set
|
||||
* @return number of records
|
||||
*/
|
||||
long count();
|
||||
|
||||
/**
|
||||
* Retrieves an instance of the record identified by the given id.
|
||||
* If the record can not be found, null is returned.
|
||||
* (better return type would be an {@link java.util.Optional} which is covered in part Functional Programming)
|
||||
* An empty result is not an error. Therefore, we do not throw an exception.
|
||||
*
|
||||
* @param id of the record to be retrieved
|
||||
* @return record of type T or null if not found
|
||||
*/
|
||||
T findById(long id);
|
||||
|
||||
/**
|
||||
* Retrieves all records of the data set.
|
||||
* If the dataset is empty an empty collection is returned.
|
||||
*
|
||||
* @return collection of all records of the data set
|
||||
*/
|
||||
Collection<T> findAll();
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package ch.zhaw.prog2.io.picturedb;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Implements the PictureDatasource Interface storing the data in
|
||||
* Character Separated Values (CSV) format, where each line consists of a record
|
||||
* whose fields are separated by the DELIMITER value ";"
|
||||
* See example file: db/picture-data.csv
|
||||
*/
|
||||
public class FilePictureDatasource implements PictureDatasource {
|
||||
// Charset to use for file encoding.
|
||||
protected static final Charset CHARSET = StandardCharsets.UTF_8;
|
||||
// Delimiter to separate record fields on a line
|
||||
protected static final String DELIMITER = ";";
|
||||
// Date format to use for date specific record fields
|
||||
protected static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
||||
|
||||
private final DateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
|
||||
|
||||
/**
|
||||
* Creates the FilePictureDatasource object with the given file path as datafile.
|
||||
* Creates the file if it does not exist.
|
||||
* Also creates an empty temp file for write operations.
|
||||
*
|
||||
* @param filepath of the file to use as database file.
|
||||
* @throws IOException if accessing or creating the file fails
|
||||
*/
|
||||
public FilePictureDatasource(String filepath) throws IOException {
|
||||
// ToDo: Implement
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void insert(Picture picture) {
|
||||
// ToDo: Implement
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void update(Picture picture) throws RecordNotFoundException {
|
||||
// ToDo: Implement
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public void delete(Picture picture) throws RecordNotFoundException {
|
||||
// ToDo: Implement
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public long count() {
|
||||
// ToDo: Correct Implementation
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public Picture findById(long id) {
|
||||
// ToDo: Correct Implementation
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public Collection<Picture> findAll() {
|
||||
// ToDo: Correct Implementation
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
public Collection<Picture> findByPosition(float longitude, float latitude, float deviation) {
|
||||
// ToDo: Correct Implementation
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package ch.zhaw.prog2.io.picturedb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Locale;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogManager;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Configuration class for Java Logging
|
||||
* Reads configuration from property file, specified in the following order:
|
||||
* - System property "java.util.logging.config.file" (also used by LogManager)
|
||||
* - file "log.properties" in working directory
|
||||
* - file "log.properties" in project resources
|
||||
* If this class is specified in system property "java.util.logging.config.class" it
|
||||
* is loaded automatically at system startup.
|
||||
* Otherwise, it can also be called at startup.
|
||||
*/
|
||||
|
||||
public class LogConfiguration {
|
||||
private static final Logger logger = Logger.getLogger(LogConfiguration.class.getCanonicalName());
|
||||
|
||||
/*
|
||||
* Static class configuration.
|
||||
* Only executed once when class is loaded.
|
||||
* Load Java logger configuration from config file
|
||||
*/
|
||||
static {
|
||||
Locale.setDefault(Locale.ROOT); // show log messages in english
|
||||
// get log config file (default uses log.properties in working directory)
|
||||
String logConfigFile = System.getProperty("java.util.logging.config.file", "log.properties");
|
||||
Path logConfigPath = Path.of(logConfigFile);
|
||||
try {
|
||||
InputStream configFileStream;
|
||||
if (Files.isReadable(logConfigPath)) {
|
||||
// if available and readable use specified file
|
||||
configFileStream = Files.newInputStream(logConfigPath);
|
||||
} else {
|
||||
// otherwise use minimal config from resources
|
||||
logConfigFile="resources:/log.properties";
|
||||
configFileStream = ClassLoader.getSystemClassLoader().getResourceAsStream("log.properties");
|
||||
}
|
||||
if (configFileStream != null) {
|
||||
LogManager.getLogManager().readConfiguration(configFileStream);
|
||||
logger.fine("Log configuration read from " + logConfigFile);
|
||||
} else {
|
||||
logger.warning("No log configuration found. Using system default settings.");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.log(Level.WARNING, "Error loading log configuration", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static String getProperty(String name) {
|
||||
return LogManager.getLogManager().getProperty(name);
|
||||
}
|
||||
|
||||
public static void setLogLevel(Class clazz, Level level) {
|
||||
Logger.getLogger(clazz.getCanonicalName()).setLevel(level);
|
||||
}
|
||||
|
||||
public static Level getLogLevel(Class clazz) {
|
||||
return Logger.getLogger(clazz.getCanonicalName()).getLevel();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
package ch.zhaw.prog2.io.picturedb;
|
||||
|
||||
import java.net.URL;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
public class Picture extends Record {
|
||||
|
||||
private final URL url;
|
||||
private final Date date;
|
||||
private final String title;
|
||||
private final float longitude;
|
||||
private final float latitude;
|
||||
|
||||
public Picture(URL url, Date date, String title, float longitude, float latitude) {
|
||||
this.url = url;
|
||||
this.date = date;
|
||||
this.title = title;
|
||||
this.longitude = longitude;
|
||||
this.latitude = latitude;
|
||||
}
|
||||
|
||||
public Picture(URL url, String title) {
|
||||
this(url, new Date(), title, 0, 0);
|
||||
}
|
||||
|
||||
protected Picture(long id, URL url, Date date, String title, float longitude, float latitude) {
|
||||
this(url,date, title, longitude, latitude);
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public URL getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
|
||||
public float getLongitude() {
|
||||
return longitude;
|
||||
}
|
||||
|
||||
public float getLatitude() {
|
||||
return latitude;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
Picture picture = (Picture) o;
|
||||
return Float.compare(picture.longitude, longitude) == 0 &&
|
||||
Float.compare(picture.latitude, latitude) == 0 &&
|
||||
url.equals(picture.url) &&
|
||||
date.equals(picture.date) &&
|
||||
title.equals(picture.title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(url, date, title, longitude, latitude);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Picture{" +
|
||||
"id=" + id +
|
||||
", url=" + url +
|
||||
", date=" + date +
|
||||
", title='" + title + '\'' +
|
||||
", longitude=" + longitude +
|
||||
", latitude=" + latitude +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package ch.zhaw.prog2.io.picturedb;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Declaration of a Datasource to store Picture records.
|
||||
* Beside the default Datasource methods, it declares an additional Picture specific query method.
|
||||
*/
|
||||
public interface PictureDatasource extends Datasource<Picture> {
|
||||
/**
|
||||
* Retrieves all images close to a a certain position.
|
||||
* All images with a deviation from the exact coordinates are returned.
|
||||
* This includes all objects in a square range
|
||||
* from [longitude - deviation / latitude - deviation]
|
||||
* to [longitude + deviation / latitude + deviation]
|
||||
*
|
||||
* @param longitude longitude coordinate of the center of the square area
|
||||
* @param latitude latitude coordinate of the center of the square area
|
||||
* @param deviation deviation from the center of the area in longitude and latitude direction
|
||||
* @return Collection of all Picture records in the area
|
||||
*/
|
||||
Collection<Picture>findByPosition(float longitude, float latitude, float deviation);
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package ch.zhaw.prog2.io.picturedb;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Scanner;
|
||||
import java.util.logging.Level;
|
||||
|
||||
/* This demo-application reads some picture data from terminal,
|
||||
* saves it to the datasource, read it from the DB and prints the result
|
||||
*/
|
||||
|
||||
public class PictureImport {
|
||||
private static final String PICTURE_DB = "db/picture-data.csv";
|
||||
private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
|
||||
private static final DateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
|
||||
private static final PrintWriter out = new PrintWriter(System.out, true);
|
||||
|
||||
|
||||
public static void main (String[] args) throws IOException {
|
||||
// initialize logger level
|
||||
LogConfiguration.setLogLevel(FilePictureDatasource.class, Level.FINE);
|
||||
|
||||
// create datasource
|
||||
PictureDatasource dataSource = new FilePictureDatasource(PICTURE_DB);
|
||||
// read picture data from the terminal
|
||||
Picture picture = createPicture();
|
||||
// save the picture to the data source
|
||||
dataSource.insert(picture);
|
||||
// read the picture back from file
|
||||
Picture readPicture = dataSource.findById(picture.getId());
|
||||
if (readPicture != null) {
|
||||
out.println("The following pictures has been saved: ");
|
||||
out.println(readPicture);
|
||||
} else {
|
||||
out.println("Picture with id=" + picture.getId() + " not found.");
|
||||
}
|
||||
|
||||
// read all pictures and list them on the console
|
||||
Collection<Picture> pictures = dataSource.findAll();
|
||||
out.println("Pictures:");
|
||||
for (Picture pict : pictures) {
|
||||
out.println(pict.toString());
|
||||
}
|
||||
}
|
||||
|
||||
static Picture createPicture() {
|
||||
// asks the values for the objects
|
||||
out.println("** Create a new picture **");
|
||||
URL url = null;
|
||||
do {
|
||||
String urlString = prompt("Picture URL: ");
|
||||
try {
|
||||
url = new URL(urlString);
|
||||
} catch (MalformedURLException e1) {
|
||||
out.println("Malformed URL: " + e1.getMessage());
|
||||
}
|
||||
} while (url == null);
|
||||
|
||||
String title = prompt("Picture title: ");
|
||||
|
||||
Date date = new Date(); // now
|
||||
try {
|
||||
date = dateFormat.parse(prompt("Picture time ("+DATE_FORMAT+") Default = now: "));
|
||||
} catch (ParseException e) {
|
||||
out.println("Unknown date format. Using "+ dateFormat.format(date));
|
||||
}
|
||||
|
||||
float longitude = 0.0f;
|
||||
try {
|
||||
longitude = Float.parseFloat(prompt("Picture position longitude: "));
|
||||
} catch (NumberFormatException e) {
|
||||
out.println("Unknown number format. Using " + longitude);
|
||||
}
|
||||
|
||||
float latitude = 0.0f;
|
||||
try {
|
||||
latitude = Float.parseFloat(prompt("Picture position latitude: "));
|
||||
} catch (NumberFormatException e) {
|
||||
out.println("Unknown number format. Using " + latitude);
|
||||
}
|
||||
|
||||
return new Picture(url, date, title, longitude, latitude);
|
||||
}
|
||||
|
||||
// prompt function -- to read input string
|
||||
static String prompt(String prompt) {
|
||||
try {
|
||||
Scanner scanner = new Scanner(System.in);
|
||||
out.print(prompt);
|
||||
out.flush();
|
||||
return scanner.nextLine().strip();
|
||||
} catch (NoSuchElementException e) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package ch.zhaw.prog2.io.picturedb;
|
||||
|
||||
/**
|
||||
* Abstract class to be used as base class for data records, which can stored in a {@link Datasource}
|
||||
* When a record is created it gets the default id of -1, indicating that it is a new record, which is not stored
|
||||
* in a DataSource.
|
||||
*/
|
||||
public abstract class Record {
|
||||
/**
|
||||
* Default id for new records, indicating, that it is not yet stored in a datasource.
|
||||
*/
|
||||
private static final long DEFAULT_ID = -1L;
|
||||
/**
|
||||
* Identifier of the record.
|
||||
*/
|
||||
protected long id = DEFAULT_ID;
|
||||
|
||||
/**
|
||||
* Set the id for this record. This method is used by the specific data set handler when adding the record to a
|
||||
* {@link Datasource}. It should not be used directly by the user.
|
||||
* @param id new id of the record, when the record is added to the data source
|
||||
*/
|
||||
protected void setId(long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the identifier of the record
|
||||
* @return identifier of the record
|
||||
*/
|
||||
public long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the status of the record.
|
||||
* @return true, if the record is not stored to the data source, false otherwise
|
||||
*/
|
||||
public boolean isNew() {
|
||||
return id == DEFAULT_ID;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package ch.zhaw.prog2.io.picturedb;
|
||||
|
||||
/**
|
||||
* Exception indicating that a record could not be found in a datasource.
|
||||
* The reason why is given as a text message.
|
||||
*/
|
||||
public class RecordNotFoundException extends Exception {
|
||||
public RecordNotFoundException() {
|
||||
}
|
||||
|
||||
public RecordNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
public RecordNotFoundException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
public RecordNotFoundException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
|
||||
public RecordNotFoundException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
|
||||
super(message, cause, enableSuppression, writableStackTrace);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
## Minimal log configuration setting decent defaults
|
||||
## Console handler configuration
|
||||
java.util.logging.ConsoleHandler.level = ALL
|
||||
|
||||
## Configure format of log messages
|
||||
java.util.logging.SimpleFormatter.format = [%1$tF %1$tT %1tZ] [%4$s] [%3$s] %5$s%6$s%n
|
||||
|
||||
## configure default log level (for all loggers, if not overwritten below)
|
||||
.level = INFO
|
||||
|
||||
## configure root logger ""
|
||||
handlers = java.util.logging.ConsoleHandler
|
||||
level = INFO
|
||||
+279
@@ -0,0 +1,279 @@
|
||||
package ch.zhaw.prog2.io.picturedb;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.LogManager;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static ch.zhaw.prog2.io.picturedb.FilePictureDatasource.*;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
|
||||
class FilePictureDatasourceTest {
|
||||
private static final long EXISTING_ID = 13;
|
||||
private static final long INEXISTENT_ID = 0;
|
||||
|
||||
private final DateFormat df = new SimpleDateFormat(DATE_FORMAT);
|
||||
private final Random random = new Random(new Date().getTime());
|
||||
|
||||
/*
|
||||
* Static class configuration.
|
||||
* Only executed once when class is loaded.
|
||||
*/
|
||||
static {
|
||||
// logger configuration
|
||||
try {
|
||||
// show log messages in english
|
||||
Locale.setDefault(Locale.ROOT);
|
||||
// load default minimal log configuration
|
||||
LogManager.getLogManager().readConfiguration(ClassLoader.getSystemResourceAsStream("log.properties"));
|
||||
// set level for class to test to WARNING (minimize log messages)
|
||||
Logger.getLogger(FilePictureDatasource.class.getCanonicalName()).setLevel(Level.WARNING);
|
||||
} catch (IOException e) {
|
||||
System.err.println("Failed to read log configuration: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Path dbTemplatePath; // path of template database
|
||||
Path dbPath; // path of temporary test database
|
||||
|
||||
PictureDatasource datasource = null; // datasource instance to test
|
||||
|
||||
FilePictureDatasourceTest() {
|
||||
URL dbTemplateUrl = FilePictureDatasourceTest.class.getClassLoader().getResource("db");
|
||||
Objects.requireNonNull(dbTemplateUrl, "Test database directory not found");
|
||||
String dbDir = new File(dbTemplateUrl.getPath()).getAbsolutePath(); // required for Windows to remove leading '/'
|
||||
String dbDirRaw = URLDecoder.decode(dbDir, CHARSET); // replace urlencoded characters, e.g. %20 -> " "
|
||||
dbTemplatePath = Path.of(dbDirRaw, "test-data-template.csv");
|
||||
dbPath = Path.of(dbDirRaw, "test-data.csv");
|
||||
}
|
||||
|
||||
|
||||
@BeforeEach
|
||||
void setUp() throws IOException {
|
||||
// initialize test database file
|
||||
Files.copy(dbTemplatePath, dbPath);
|
||||
// setup datasource
|
||||
datasource = new FilePictureDatasource(dbPath.toString());
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void tearDown() throws IOException {
|
||||
// cleanup test database file
|
||||
Files.deleteIfExists(dbPath);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void insert() {
|
||||
Picture testPicture = createPicture("http://test.url/hallo.img", "Test picture");
|
||||
assertEquals(-1, testPicture.getId(), "New picture must have Id -1");
|
||||
datasource.insert(testPicture);
|
||||
assertNotEquals(-1, testPicture.getId(), "Insert must set new id to picture");
|
||||
assertTrue(testPicture.getId() > 14, "Id must be larger than last existing");
|
||||
assertEquals(15, testPicture.getId(), "Id must be 1 larger than current highest");
|
||||
try {
|
||||
String insertedLine = readLineNo(4);
|
||||
assertNotNull(insertedLine, "Inserted line does not exist");
|
||||
assertEquals(pictureToCsvLine(testPicture), insertedLine);
|
||||
} catch (IOException e) {
|
||||
fail("Failed reading inserted picture record");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void insertNull() {
|
||||
assertThrows(NullPointerException.class, () -> datasource.insert(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void delete() {
|
||||
long pictureIdToDelete = EXISTING_ID;
|
||||
Picture pictureToDelete = datasource.findById(pictureIdToDelete);
|
||||
assumeTrue(pictureToDelete != null, "Picture to delete not found");
|
||||
|
||||
try {
|
||||
datasource.delete(pictureToDelete);
|
||||
} catch (RecordNotFoundException e) {
|
||||
fail("Failed to delete picture", e);
|
||||
}
|
||||
|
||||
try {
|
||||
String deletedRecord = readLineWithId(pictureIdToDelete);
|
||||
assertNull(deletedRecord, "Record still found after delete");
|
||||
} catch (IOException e) {
|
||||
fail("Failed to read deleted record");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteNull() {
|
||||
assertThrows(NullPointerException.class, () -> datasource.delete(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void deleteInexistent() {
|
||||
Picture testPicture = createPicture("http://test.url/hallo.img", "Test picture");
|
||||
testPicture.setId(INEXISTENT_ID);
|
||||
assertThrows(RecordNotFoundException.class, () -> datasource.delete(testPicture));
|
||||
}
|
||||
|
||||
@Test
|
||||
void update() {
|
||||
Picture originalPicture = datasource.findById(EXISTING_ID);
|
||||
assumeTrue(originalPicture != null);
|
||||
assumeTrue(originalPicture.id == EXISTING_ID);
|
||||
|
||||
Date updatedDate = new Date(originalPicture.getDate().getTime() + 60_000);
|
||||
URL updatedURL = originalPicture.getUrl();
|
||||
try {
|
||||
updatedURL = new URL(originalPicture.getUrl() + "/updated");
|
||||
} catch (MalformedURLException e) {
|
||||
fail("Invalid URL format", e);
|
||||
}
|
||||
Picture updatedPicture = new Picture(
|
||||
originalPicture.id,
|
||||
updatedURL,
|
||||
updatedDate,
|
||||
originalPicture.getTitle()+" (updated)",
|
||||
originalPicture.getLongitude() + 10,
|
||||
originalPicture.getLatitude() + 10);
|
||||
|
||||
try {
|
||||
datasource.update(updatedPicture);
|
||||
} catch (RecordNotFoundException e) {
|
||||
fail("Test record not found for update", e);
|
||||
}
|
||||
|
||||
Picture readUpdatedPicture = datasource.findById(originalPicture.getId());
|
||||
assertNotNull(readUpdatedPicture, "updated picture not found");
|
||||
assertEquals(updatedPicture.id, readUpdatedPicture.id);
|
||||
assertEquals(updatedPicture.getUrl(), readUpdatedPicture.getUrl());
|
||||
assertEquals(updatedPicture.getDate(), readUpdatedPicture.getDate());
|
||||
assertEquals(updatedPicture.getTitle(), readUpdatedPicture.getTitle());
|
||||
assertEquals(updatedPicture.getLatitude(), readUpdatedPicture.getLatitude());
|
||||
assertEquals(updatedPicture.getLongitude(), readUpdatedPicture.getLongitude());
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateNull() {
|
||||
assertThrows(NullPointerException.class, () -> datasource.update(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void updateInexistent() {
|
||||
Picture testPicture = createPicture("http://test.url/hallo.img", "Test picture");
|
||||
testPicture.setId(INEXISTENT_ID);
|
||||
assertThrows(RecordNotFoundException.class, () -> datasource.update(testPicture));
|
||||
}
|
||||
|
||||
@Test
|
||||
void count() {
|
||||
assertEquals(3, datasource.count(), "Count for initial datasource not correct");
|
||||
datasource.insert(createPicture("http://test.url/hallo.img", "Test picture"));
|
||||
assertEquals(4, datasource.count(), "Count for updated datasource not correct");
|
||||
}
|
||||
|
||||
@Test
|
||||
void findById() {
|
||||
Picture foundPicture = datasource.findById(EXISTING_ID);
|
||||
assertNotNull(foundPicture, "Picture not found");
|
||||
assertEquals("2013-05-07 13:45:13", df.format(foundPicture.getDate()));
|
||||
assertEquals("http://blog.stackoverflow.com/wp-content/uploads/code_monkey_colour.jpg",
|
||||
foundPicture.getUrl().toExternalForm());
|
||||
assertEquals("Need a coder", foundPicture.getTitle());
|
||||
assertEquals(-71.098270, foundPicture.getLongitude(), 0.00001);
|
||||
assertEquals(42.302583, foundPicture.getLatitude(), 0.00001);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findByIdInexistent() {
|
||||
Picture foundPicture = datasource.findById(INEXISTENT_ID);
|
||||
assertNull(foundPicture, "Inexistent Id found: " + INEXISTENT_ID);
|
||||
}
|
||||
|
||||
@Test
|
||||
void findAll() {
|
||||
Collection<Picture> pictures = datasource.findAll();
|
||||
assertNotNull(pictures, "Collection of pictures must not be null");
|
||||
assertEquals(countLines(), pictures.size(), "Number of records does not match number of found pictures");
|
||||
for (Picture picture : pictures) {
|
||||
assertNotNull(picture, "Found <null> picture in collection");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void findByPosition() {
|
||||
Collection<Picture> pictures = datasource.findByPosition(-75, 41, 4);
|
||||
assertNotNull(pictures);
|
||||
assertEquals(2, pictures.size(), "Not correct amount of items found at position");
|
||||
|
||||
pictures = datasource.findByPosition(55, 23, 1);
|
||||
assertEquals(0, pictures.size(), "Found items not to be found");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Helper methods
|
||||
*/
|
||||
private Picture createPicture(String url, String title) {
|
||||
URL testURL = null;
|
||||
try {
|
||||
testURL = new URL(url);
|
||||
} catch (MalformedURLException e) {
|
||||
fail("Invalid URL format", e);
|
||||
}
|
||||
float longitude = -180 + random.nextFloat() * 360; // range [-180..+180[
|
||||
float latitude = -90 + random.nextFloat() * 180; // range [-90..+90[
|
||||
return new Picture(testURL, new Date(), title, longitude, latitude);
|
||||
}
|
||||
|
||||
private String readLineNo(int lineNo) throws IOException {
|
||||
try (Stream<String> lineStream = Files.lines(dbPath, CHARSET)) {
|
||||
return lineStream.skip(lineNo-1).findFirst().orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
private String readLineWithId(long id) throws IOException {
|
||||
try (Stream<String> lineStream = Files.lines(dbPath, CHARSET)) {
|
||||
return lineStream.filter(line -> line.strip().startsWith(id+DELIMITER)).findFirst().orElse(null);
|
||||
}
|
||||
}
|
||||
|
||||
private long countLines() {
|
||||
try (Stream<String> lineStream = Files.lines(dbPath, CHARSET)) {
|
||||
return lineStream.filter(Predicate.not(String::isBlank)).count();
|
||||
} catch (IOException e) {
|
||||
fail("Failed to count lines in db file", e);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private String pictureToCsvLine(Picture picture) {
|
||||
assertNotNull(picture, "Picture must not be null");
|
||||
return String.join(DELIMITER,
|
||||
String.valueOf(picture.getId()),
|
||||
df.format(picture.getDate()),
|
||||
String.valueOf(picture.getLongitude()),
|
||||
String.valueOf(picture.getLatitude()),
|
||||
picture.getTitle(),
|
||||
picture.getUrl().toExternalForm()
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
1;2014-03-17 14:30:05;2.324744;48.864506;Another Monkey;http://www.codemonkey.in/images/Code-Monkey.png
|
||||
14;2014-04-01 02:17:33;77.598736;40.979842;Bête à coder;http://www2.craven.fr/blojsom/resources/default/codemonkey.jpg
|
||||
13;2013-05-07 13:45:13;-71.098270;42.302583;Need a coder;http://blog.stackoverflow.com/wp-content/uploads/code_monkey_colour.jpg
|
||||
|
Reference in New Issue
Block a user