Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision

Target

Select target project
  • bragearn/examples
  • johngu/examples
  • krisschn/examples
  • erikbd/examples
  • helenesm/examples
  • balazor/examples
  • htechter/examples
  • aslakho/examples
  • jonri/examples
  • andreski/examples
  • sigriksc/examples
  • norasbr/examples
  • jannash/examples
  • smledsaa/examples
  • mtorre/examples
  • tdt4140-staff/examples
16 results
Select Git revision
Show changes
Showing
with 657 additions and 201 deletions
package tdt4140.gr1800.app.db; package tdt4140.gr1800.app.db;
import java.sql.Connection; import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager; import java.sql.DriverManager;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Time;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Collection; import java.util.Collection;
import java.util.Scanner;
import tdt4140.gr1800.app.core.GeoLocation;
import tdt4140.gr1800.app.core.GeoLocations; import tdt4140.gr1800.app.core.GeoLocations;
import tdt4140.gr1800.app.core.Person; import tdt4140.gr1800.app.core.Person;
...@@ -13,34 +21,61 @@ public class DbAccessImpl extends AbstractDbAccessImpl { ...@@ -13,34 +21,61 @@ public class DbAccessImpl extends AbstractDbAccessImpl {
private final DbAccessHelper helper; private final DbAccessHelper helper;
private DbAccessImpl(DbAccessHelper helper) { private DbAccessImpl(final DbAccessHelper helper) {
this.helper = helper; this.helper = helper;
} }
public DbAccessImpl(Connection dbConnection) { public DbAccessImpl(final Connection dbConnection) {
this(new DbAccessHelper(dbConnection)); this(new DbAccessHelper(dbConnection));
} }
public DbAccessImpl(String connectionUri, String user, String pass) throws SQLException { public DbAccessImpl(final String connectionUri, final String user, final String pass) throws SQLException {
this(DriverManager.getConnection(connectionUri, user, pass)); this(DriverManager.getConnection(connectionUri, user, pass));
} }
public DbAccessImpl(String connectionUri) throws SQLException { public DbAccessImpl(final String connectionUri) throws SQLException {
this(connectionUri, "SA", ""); this(connectionUri, "SA", "");
} }
// //
public void executeStatements(final String path, final boolean cleanUp) throws SQLException {
final Statement dbStatement = helper.getDbConnection().createStatement();
final StringBuilder buffer = new StringBuilder();
try (Scanner scanner = new Scanner(getClass().getResourceAsStream(path))) {
while (scanner.hasNextLine()) {
final String line = scanner.nextLine();
final int pos = line.indexOf(";");
if (pos >= 0) {
buffer.append(line.substring(0, pos + 1));
final String sql = buffer.toString();
buffer.setLength(0);
if (pos < line.length()) {
buffer.append(line.substring(pos + 1));
}
if (cleanUp || (! sql.startsWith("DROP"))) {
dbStatement.execute(sql);
}
} else {
buffer.append(line);
buffer.append("\n");
}
}
}
}
//
@Override @Override
public synchronized Person createPerson(String name, String email) { public synchronized Person createPerson(final String name, final String email) {
Person person = super.createPerson(name, email); final Person person = super.createPerson(name, email);
int id = helper.executeDbInsertGettingIdentity(String.format("INSERT INTO person (name, email) VALUES ('%s', '%s')", name, email)); final int id = helper.executeDbInsertGettingIdentity(String.format("INSERT INTO person (name, email) VALUES ('%s', '%s')", name, email));
personIds.set(person, id); personIds.set(person, id);
return person; return person;
} }
protected Person createPerson(int id, String name, String email) { protected Person createPerson(final int id, final String name, final String email) {
Person person = new Person(); final Person person = new Person();
person.setName(name); person.setName(name);
person.setEmail(email); person.setEmail(email);
personIds.remove(id); personIds.remove(id);
...@@ -49,17 +84,17 @@ public class DbAccessImpl extends AbstractDbAccessImpl { ...@@ -49,17 +84,17 @@ public class DbAccessImpl extends AbstractDbAccessImpl {
} }
@Override @Override
public Collection<Person> getAllPersons(boolean refresh) { public Collection<Person> getAllPersons(final boolean refresh) {
if (refresh) { if (refresh) {
personIds.clear(); personIds.clear();
ResultSet result = helper.executeQuery("SELECT id, name, email FROM person"); final ResultSet result = helper.executeQuery("SELECT id, name, email FROM person");
try { try {
while (result.next()) { while (result.next()) {
int id = result.getInt(1); final int id = result.getInt(1);
String name = result.getString(2), email = result.getString(3); final String name = result.getString(2), email = result.getString(3);
createPerson(id, name, email); createPerson(id, name, email);
} }
} catch (SQLException e) { } catch (final SQLException e) {
helper.throwException(e); helper.throwException(e);
} }
} }
...@@ -67,19 +102,19 @@ public class DbAccessImpl extends AbstractDbAccessImpl { ...@@ -67,19 +102,19 @@ public class DbAccessImpl extends AbstractDbAccessImpl {
} }
@Override @Override
public Person getPerson(int id, boolean refresh) { public Person getPerson(final int id, final boolean refresh) {
Person person = null; Person person = null;
if (! refresh) { if (! refresh) {
person = super.getPerson(id, false); person = super.getPerson(id, false);
} }
if (person == null || refresh) { if (person == null || refresh) {
ResultSet result = helper.executeQuery("SELECT id, name, email FROM person WHERE id = ?", id); final ResultSet result = helper.executeQuery("SELECT id, name, email FROM person WHERE id = ?", id);
try { try {
if (result.next()) { if (result.next()) {
String name = result.getString(2), email = result.getString(3); final String name = result.getString(2), email = result.getString(3);
person = createPerson(id, name, email); person = createPerson(id, name, email);
} }
} catch (SQLException e) { } catch (final SQLException e) {
helper.throwException(e); helper.throwException(e);
} }
} }
...@@ -87,20 +122,20 @@ public class DbAccessImpl extends AbstractDbAccessImpl { ...@@ -87,20 +122,20 @@ public class DbAccessImpl extends AbstractDbAccessImpl {
} }
@Override @Override
public Person getPersonByName(String name, boolean refresh) { public Person getPersonByName(final String name, final boolean refresh) {
Person person = null; Person person = null;
if (! refresh) { if (! refresh) {
person = super.getPersonByName(name, false); person = super.getPersonByName(name, false);
} }
if (person == null || refresh) { if (person == null || refresh) {
ResultSet result = helper.executeQuery("SELECT id, name, email FROM person WHERE name = ?", name); final ResultSet result = helper.executeQuery("SELECT id, name, email FROM person WHERE name = ?", name);
try { try {
if (result.next()) { if (result.next()) {
int id = result.getInt(1); final int id = result.getInt(1);
String dbName = result.getString(2), email = result.getString(3); final String dbName = result.getString(2), email = result.getString(3);
person = createPerson(id, dbName, email); person = createPerson(id, dbName, email);
} }
} catch (SQLException e) { } catch (final SQLException e) {
helper.throwException(e); helper.throwException(e);
} }
} }
...@@ -108,20 +143,20 @@ public class DbAccessImpl extends AbstractDbAccessImpl { ...@@ -108,20 +143,20 @@ public class DbAccessImpl extends AbstractDbAccessImpl {
} }
@Override @Override
public Person getPersonByEmail(String email, boolean refresh) { public Person getPersonByEmail(final String email, final boolean refresh) {
Person person = null; Person person = null;
if (! refresh) { if (! refresh) {
person = super.getPersonByEmail(email, false); person = super.getPersonByEmail(email, false);
} }
if (person == null || refresh) { if (person == null || refresh) {
ResultSet result = helper.executeQuery("SELECT id, name, email FROM person WHERE email = ?", email); final ResultSet result = helper.executeQuery("SELECT id, name, email FROM person WHERE email = ?", email);
try { try {
if (result.next()) { if (result.next()) {
int id = result.getInt(1); final int id = result.getInt(1);
String name = result.getString(2), dbEmail = result.getString(3); final String name = result.getString(2), dbEmail = result.getString(3);
person = createPerson(id, name, dbEmail); person = createPerson(id, name, dbEmail);
} }
} catch (SQLException e) { } catch (final SQLException e) {
helper.throwException(e); helper.throwException(e);
} }
} }
...@@ -129,13 +164,13 @@ public class DbAccessImpl extends AbstractDbAccessImpl { ...@@ -129,13 +164,13 @@ public class DbAccessImpl extends AbstractDbAccessImpl {
} }
@Override @Override
public synchronized void updatePersonData(Person person) { public synchronized void updatePersonData(final Person person) {
helper.executeDbStatement("UPDATE person SET name = ?, email = ? WHERE id = ?", person.getName(), person.getEmail(), getId(person)); helper.executeDbStatement("UPDATE person SET name = ?, email = ? WHERE id = ?", person.getName(), person.getEmail(), getId(person));
} }
@Override @Override
public synchronized void deletePerson(Person person) { public synchronized void deletePerson(final Person person) {
int id = getId(person); final int id = getId(person);
super.deletePerson(person); super.deletePerson(person);
helper.executeDbStatement("DELETE FROM person WHERE id = ?", id); helper.executeDbStatement("DELETE FROM person WHERE id = ?", id);
// not needed with ON DELETE CASCADE set on foreign keys // not needed with ON DELETE CASCADE set on foreign keys
...@@ -146,9 +181,9 @@ public class DbAccessImpl extends AbstractDbAccessImpl { ...@@ -146,9 +181,9 @@ public class DbAccessImpl extends AbstractDbAccessImpl {
// //
@Override @Override
public GeoLocations createGeoLocations(Person owner) { public GeoLocations createGeoLocations(final Person owner) {
GeoLocations geoLocations = super.createGeoLocations(owner); final GeoLocations geoLocations = super.createGeoLocations(owner);
int id = helper.executeDbInsertGettingIdentity(String.format("INSERT INTO geoLocations (ownerId) VALUES ('%s')", getId(owner))); final int id = helper.executeDbInsertGettingIdentity(String.format("INSERT INTO geoLocations (ownerId) VALUES ('%s')", getId(owner)));
geoLocationsIds.set(geoLocations, id); geoLocationsIds.set(geoLocations, id);
return geoLocations; return geoLocations;
} }
...@@ -159,46 +194,51 @@ public class DbAccessImpl extends AbstractDbAccessImpl { ...@@ -159,46 +194,51 @@ public class DbAccessImpl extends AbstractDbAccessImpl {
} }
@Override @Override
public Collection<GeoLocations> getGeoLocations(Person owner, boolean refresh) { public Collection<GeoLocations> getGeoLocations(final Person owner, final boolean refresh) {
Collection<GeoLocations> existingGeoLocations = super.getGeoLocations(owner, false); final Collection<GeoLocations> existingGeoLocations = super.getGeoLocations(owner, false);
if (refresh || existingGeoLocations.isEmpty()) { if (refresh || existingGeoLocations.isEmpty()) {
owner.removeGeolocations((String[]) null); owner.removeGeolocations((String[]) null);
geoLocationsIds.removeAll(existingGeoLocations); geoLocationsIds.removeAll(existingGeoLocations);
existingGeoLocations.clear(); existingGeoLocations.clear();
int ownerId = getId(owner); final int ownerId = getId(owner);
ResultSet result = helper.executeQuery("SELECT id, path, name, description, date, time FROM geoLocations WHERE ownerId = ?", ownerId); final ResultSet result = helper.executeQuery("SELECT id, path, name, description, date, time, zone FROM geoLocations WHERE ownerId = ?", ownerId);
try { try {
while (result.next()) { while (result.next()) {
int id = result.getInt(1); final int id = result.getInt(1);
boolean path = result.getBoolean(2); final boolean path = result.getBoolean(2);
String name = result.getString(3), description = result.getString(3); final String name = result.getString(3), description = result.getString(4);
GeoLocations geoLocations = new GeoLocations(owner); final GeoLocations geoLocations = new GeoLocations(owner);
owner.addGeolocations(geoLocations); owner.addGeolocations(geoLocations);
geoLocations.setPath(path); geoLocations.setPath(path);
geoLocations.setName(name); geoLocations.setName(name);
geoLocations.setDescription(description); geoLocations.setDescription(description);
// TODO: date and time final Date date = result.getDate(5);
final Time time = result.getTime(6);
final String zone = result.getString(7);
geoLocations.setDate(date != null ? date.toLocalDate() : null);
geoLocations.setTime(time != null ? time.toLocalTime() : null);
geoLocations.setZone(zone != null ? ZoneId.of(zone) : null);
existingGeoLocations.add(geoLocations); existingGeoLocations.add(geoLocations);
geoLocationsIds.set(geoLocations, id); geoLocationsIds.set(geoLocations, id);
ResultSet tagResults = helper.executeQuery(String.format("SELECT tag FROM tag WHERE ownerId = ? AND ownerType = '%s'", TagOwnerType.GLS), id); final ResultSet tagResults = helper.executeQuery(String.format("SELECT tag FROM tag WHERE ownerId = ? AND ownerType = '%s'", TagOwnerType.GLS), id);
while (tagResults.next()) { while (tagResults.next()) {
geoLocations.addTags(tagResults.getString(1)); geoLocations.addTags(tagResults.getString(1));
} }
} }
} catch (SQLException e) { } catch (final SQLException e) {
helper.throwException(e); helper.throwException(e);
} }
ResultSet tagResult = helper.executeQuery(String.format("SELECT geoLocations.id, tag.tag FROM geoLocations, tag WHERE geoLocations.ownerId = ? AND tag.ownerId = geoLocations.id AND ownerType = '%s'", TagOwnerType.GLS), ownerId); final ResultSet tagResult = helper.executeQuery(String.format("SELECT geoLocations.id, tag.tag FROM geoLocations, tag WHERE geoLocations.ownerId = ? AND tag.ownerId = geoLocations.id AND ownerType = '%s'", TagOwnerType.GLS), ownerId);
try { try {
while (tagResult.next()) { while (tagResult.next()) {
int geoLocationsId = tagResult.getInt(1); final int geoLocationsId = tagResult.getInt(1);
String tag = tagResult.getString(2); final String tag = tagResult.getString(2);
GeoLocations geoLocations = geoLocationsIds.get(geoLocationsId); final GeoLocations geoLocations = geoLocationsIds.get(geoLocationsId);
if (geoLocations != null) { if (geoLocations != null) {
geoLocations.addTags(tag); geoLocations.addTags(tag);
} }
} }
} catch (SQLException e) { } catch (final SQLException e) {
helper.throwException(e); helper.throwException(e);
} }
} }
...@@ -206,14 +246,17 @@ public class DbAccessImpl extends AbstractDbAccessImpl { ...@@ -206,14 +246,17 @@ public class DbAccessImpl extends AbstractDbAccessImpl {
} }
@Override @Override
public void updateGeoLocationsData(GeoLocations geoLocations) { public void updateGeoLocationsData(final GeoLocations geoLocations) {
boolean path = geoLocations.isPath(); final boolean path = geoLocations.isPath();
String name = geoLocations.getName(), desc = geoLocations.getDescription(); final String name = geoLocations.getName(), desc = geoLocations.getDescription();
int ownerId = getId(geoLocations); final LocalDate date = geoLocations.getDate();
helper.executeDbStatement("UPDATE geoLocations SET path = ?, name = ?, description = ? WHERE id = ?", path, name, desc, ownerId); final LocalTime time = geoLocations.getTime();
final String zone = (geoLocations.getZone() != null ? geoLocations.getZone().getId() : null);
final int ownerId = getId(geoLocations);
helper.executeDbStatement("UPDATE geoLocations SET path = ?, name = ?, description = ?, date = ?, time = ?, zone = ? WHERE id = ?", path, name, desc, Date.valueOf(date), Time.valueOf(time), zone, ownerId);
deleteTags(ownerId, TagOwnerType.GLS); deleteTags(ownerId, TagOwnerType.GLS);
String insertStatement = "INSERT INTO tag (ownerId, ownerType, tag) VALUES "; String insertStatement = "INSERT INTO tag (ownerId, ownerType, tag) VALUES ";
String[] tags = geoLocations.getTags(); final String[] tags = geoLocations.getTags();
for (int i = 0; i < tags.length; i++) { for (int i = 0; i < tags.length; i++) {
if (i > 0) { if (i > 0) {
insertStatement += ", "; insertStatement += ", ";
...@@ -223,15 +266,22 @@ public class DbAccessImpl extends AbstractDbAccessImpl { ...@@ -223,15 +266,22 @@ public class DbAccessImpl extends AbstractDbAccessImpl {
helper.executeDbStatement(insertStatement); helper.executeDbStatement(insertStatement);
} }
protected void deleteTags(int ownerId, TagOwnerType ownerType) { protected void deleteTags(final int ownerId, final TagOwnerType ownerType) {
helper.executeDbStatement(String.format("DELETE FROM tag WHERE ownerId = ? AND ownerType = '%s'", ownerType), ownerId); helper.executeDbStatement(String.format("DELETE FROM tag WHERE ownerId = ? AND ownerType = '%s'", ownerType), ownerId);
} }
@Override @Override
public void deleteGeoLocations(GeoLocations geoLocations) { public void deleteGeoLocations(final GeoLocations geoLocations) {
int ownerId = getId(geoLocations); final int ownerId = getId(geoLocations);
super.deleteGeoLocations(geoLocations); super.deleteGeoLocations(geoLocations);
helper.executeDbStatement("DELETE FROM geoLocations WHERE id = ?", ownerId); helper.executeDbStatement("DELETE FROM geoLocations WHERE id = ?", ownerId);
deleteTags(ownerId, TagOwnerType.GLS); deleteTags(ownerId, TagOwnerType.GLS);
} }
//
@Override
public void updateGeoLocationData(final GeoLocations geoLocations, final GeoLocation geoLocation) {
throw new UnsupportedOperationException("NYI");
}
} }
...@@ -6,38 +6,106 @@ import java.util.Collection; ...@@ -6,38 +6,106 @@ import java.util.Collection;
import tdt4140.gr1800.app.core.GeoLocated; import tdt4140.gr1800.app.core.GeoLocated;
import tdt4140.gr1800.app.core.GeoLocation; import tdt4140.gr1800.app.core.GeoLocation;
import tdt4140.gr1800.app.core.GeoLocations; import tdt4140.gr1800.app.core.GeoLocations;
import tdt4140.gr1800.app.core.GeoLocationsOwner;
import tdt4140.gr1800.app.core.Person; import tdt4140.gr1800.app.core.Person;
/* /*
* CRUD interface for our domain: * class diagram:
* *
* @startuml * @startuml
* class GeoLocationsOwner { * class GeoLocationsOwner {
* String id
* } * }
*
* class Person { * class Person {
* String name * String name
* String email * String email
* } * }
*
* class TimedTaggedImpl {
* LocalDate date
* LocalTime time
* ZoneId zone
* String[] tags
* }
*
* GeoLocationsOwner <|-- Person * GeoLocationsOwner <|-- Person
*
* GeoLocationsOwner *-- GeoLocations: owner
*
* class GeoLocations { * class GeoLocations {
* String name * String name
* String description * String description
* LocalDate date
* LocalTime time
* ZoneId zone
* String[] tags
* } * }
* GeoLocationsOwner *-- GeoLocations: owner *
* GeoLocations --|> TimedTaggedImpl
*
* class GeoLocation { * class GeoLocation {
* int elevation * int elevation
* LocalTime time * LocalTime time
* String name * String name
* String description * String description
* } * }
* GeoLocation --|> TimedTaggedImpl
*
* GeoLocations *-- GeoLocation * GeoLocations *-- GeoLocation
* GeoLocation *-- LatLong * GeoLocation *-- LatLong
* @enduml * @enduml
*/ */
/*
* ER diagram interface for our domain:
*
* @startuml
* entity person {
* * id INTEGER GENERATED
* * name varchar(80)
* * email varchar(80)
* }
*
* entity geoLocations {
* * id INTEGER GENERATED
* path boolean
* name varchar(80)
* description varchar(200)
* date date
* time time
* zone varchar(20)
* }
*
* person --{ geoLocations: ownerId
*
* entity geoLocation {
* * id INTEGER GENERATED
* name varchar(80)
* description varchar(200)
* * latitude decimal
* * longitude decimal
* elevation int
* date date
* time time
* zone varchar(20)
* }
*
* geoLocations --{ geoLocation: ownerId
*
* entity tags {
* * ownerType char(3)
* * tag varchar(15)
* }
*
* geoLocations --{ tags: ownerId
* geoLocation --{ tags: ownerId
*
* @enduml
*/
public interface IDbAccess { public interface IDbAccess {
public IdProvider<Person> getPersonIdProvider();
// Create // Create
public Person createPerson(String name, String email); public Person createPerson(String name, String email);
public GeoLocations createGeoLocations(Person owner); public GeoLocations createGeoLocations(Person owner);
...@@ -54,7 +122,7 @@ public interface IDbAccess { ...@@ -54,7 +122,7 @@ public interface IDbAccess {
// Update // Update
public void updatePersonData(Person person); public void updatePersonData(Person person);
public void updateGeoLocationsData(GeoLocations geoLocations); public void updateGeoLocationsData(GeoLocations geoLocations);
public void updateGeoLocationData(GeoLocations geoLocations, GeoLocations geoLocation); public void updateGeoLocationData(GeoLocations geoLocations, GeoLocation geoLocation);
// Delete // Delete
public void deletePerson(Person person); public void deletePerson(Person person);
......
...@@ -4,17 +4,27 @@ import java.util.Collection; ...@@ -4,17 +4,27 @@ import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
public class IdMap<T> { public class IdMap<T> implements IdProvider<T> {
protected Map<Integer, T> id2o = new HashMap<Integer, T>(); protected Map<Integer, T> id2o = new HashMap<Integer, T>();
protected Map<T, Integer> o2id = new HashMap<T, Integer>(); protected Map<T, Integer> o2id = new HashMap<T, Integer>();
public T get(int id) { public int size() {
return o2id.size();
}
public T get(final int id) {
return id2o.get(id); return id2o.get(id);
} }
public int getId(T o) { @Override
Integer id = o2id.get(o); public boolean hasId(final T t) {
return o2id.containsKey(t);
}
@Override
public int getId(final T o) {
final Integer id = o2id.get(o);
return (id != null ? id : -1); return (id != null ? id : -1);
} }
...@@ -28,7 +38,7 @@ public class IdMap<T> { ...@@ -28,7 +38,7 @@ public class IdMap<T> {
// //
void set(T o, int id) { public void set(final T o, final int id) {
if (o2id.containsKey(o)) { if (o2id.containsKey(o)) {
throw new IllegalStateException(o + " already has the id " + o2id.get(o)); throw new IllegalStateException(o + " already has the id " + o2id.get(o));
} }
...@@ -39,29 +49,29 @@ public class IdMap<T> { ...@@ -39,29 +49,29 @@ public class IdMap<T> {
o2id.put(o, id); o2id.put(o, id);
} }
void clear() { public void clear() {
o2id.clear(); o2id.clear();
id2o.clear(); id2o.clear();
} }
private void remove(T o, int id) { private void remove(final T o, final int id) {
o2id.remove(o); o2id.remove(o);
id2o.remove(id); id2o.remove(id);
} }
void remove(T o) { public void remove(final T o) {
if (o2id.containsKey(o)) { if (o2id.containsKey(o)) {
remove(o, o2id.get(o)); remove(o, o2id.get(o));
} }
} }
void removeAll(Iterable<T> os) { public void removeAll(final Iterable<T> os) {
for (T o : os) { for (final T o : os) {
remove(o); remove(o);
} }
} }
void remove(int id) { public void remove(final int id) {
if (id2o.containsKey(id)) { if (id2o.containsKey(id)) {
remove(id2o.get(id), id); remove(id2o.get(id), id);
} }
......
package tdt4140.gr1800.app.db;
public interface IdProvider<T> {
public boolean hasId(T t);
public int getId(T t);
}
...@@ -5,6 +5,15 @@ import java.io.InputStream; ...@@ -5,6 +5,15 @@ import java.io.InputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
/**
* Incomplete implementation of **IDocumentStorage**, to simplify implementing ones for specific document and location types.
* The main missing methods are for getting and setting the current document, creating an empty one and
* creating an **InputStream** from a location.
* @author hal
*
* @param <D> the document type
* @param <L> the location type
*/
public abstract class AbstractDocumentStorageImpl<D, L> implements IDocumentStorage<L>, IDocumentPersistence<D, L> { public abstract class AbstractDocumentStorageImpl<D, L> implements IDocumentStorage<L>, IDocumentPersistence<D, L> {
private L documentLocation; private L documentLocation;
...@@ -15,46 +24,61 @@ public abstract class AbstractDocumentStorageImpl<D, L> implements IDocumentStor ...@@ -15,46 +24,61 @@ public abstract class AbstractDocumentStorageImpl<D, L> implements IDocumentStor
} }
@Override @Override
public void setDocumentLocation(L documentLocation) { public void setDocumentLocation(final L documentLocation) {
L oldDocumentLocation = this.documentLocation; final L oldDocumentLocation = this.documentLocation;
this.documentLocation = documentLocation; this.documentLocation = documentLocation;
fireDocumentLocationChanged(oldDocumentLocation); fireDocumentLocationChanged(oldDocumentLocation);
} }
protected void setDocumentAndLocation(D document, L documentLocation) { protected void setDocumentAndLocation(final D document, final L documentLocation) {
setDocument(document); setDocument(document);
setDocumentLocation(documentLocation); setDocumentLocation(documentLocation);
} }
/**
* Returns the current document.
* @return the current document
*/
protected abstract D getDocument(); protected abstract D getDocument();
/**
* Sets the current document
* @param document the new document
*/
protected abstract void setDocument(D document); protected abstract void setDocument(D document);
// //
private Collection<IDocumentStorageListener<L>> documentListeners = new ArrayList<IDocumentStorageListener<L>>(); private final Collection<IDocumentStorageListener<L>> documentListeners = new ArrayList<IDocumentStorageListener<L>>();
public void addDocumentStorageListener(IDocumentStorageListener<L> documentStorageListener) { @Override
public void addDocumentStorageListener(final IDocumentStorageListener<L> documentStorageListener) {
documentListeners.add(documentStorageListener); documentListeners.add(documentStorageListener);
} }
public void removeDocumentStorageListener(IDocumentStorageListener<L> documentStorageListener) { @Override
public void removeDocumentStorageListener(final IDocumentStorageListener<L> documentStorageListener) {
documentListeners.remove(documentStorageListener); documentListeners.remove(documentStorageListener);
} }
protected void fireDocumentLocationChanged(L oldDocumentLocation) { protected void fireDocumentLocationChanged(final L oldDocumentLocation) {
for (IDocumentStorageListener<L> documentStorageListener : documentListeners) { for (final IDocumentStorageListener<L> documentStorageListener : documentListeners) {
documentStorageListener.documentLocationChanged(documentLocation, oldDocumentLocation); documentStorageListener.documentLocationChanged(documentLocation, oldDocumentLocation);
} }
} }
protected void fireDocumentChanged(D oldDocument) { protected void fireDocumentChanged(final D oldDocument) {
for (IDocumentStorageListener<L> documentListener : documentListeners) { for (final IDocumentStorageListener<L> documentListener : documentListeners) {
if (documentListener instanceof IDocumentListener) { if (documentListener instanceof IDocumentListener) {
((IDocumentListener<D, L>) documentListener).documentChanged(getDocument(), oldDocument); ((IDocumentListener<D, L>) documentListener).documentChanged(getDocument(), oldDocument);
} }
} }
} }
/**
* Creates a new and empty document.
* @return
*/
protected abstract D createDocument(); protected abstract D createDocument();
@Override @Override
...@@ -62,13 +86,19 @@ public abstract class AbstractDocumentStorageImpl<D, L> implements IDocumentStor ...@@ -62,13 +86,19 @@ public abstract class AbstractDocumentStorageImpl<D, L> implements IDocumentStor
setDocumentAndLocation(createDocument(), null); setDocumentAndLocation(createDocument(), null);
} }
protected abstract InputStream toInputStream(L storage) throws IOException; /**
* Creates an ImportStream from a location
* @param location
* @return
* @throws IOException
*/
protected abstract InputStream toInputStream(L location) throws IOException;
@Override @Override
public void openDocument(L storage) throws IOException { public void openDocument(final L storage) throws IOException {
try (InputStream input = toInputStream(storage)){ try (InputStream input = toInputStream(storage)){
setDocumentAndLocation(loadDocument(input), storage); setDocumentAndLocation(loadDocument(input), storage);
} catch (Exception e) { } catch (final Exception e) {
throw new IOException(e); throw new IOException(e);
} }
} }
...@@ -77,23 +107,23 @@ public abstract class AbstractDocumentStorageImpl<D, L> implements IDocumentStor ...@@ -77,23 +107,23 @@ public abstract class AbstractDocumentStorageImpl<D, L> implements IDocumentStor
public void saveDocument() throws IOException { public void saveDocument() throws IOException {
try { try {
saveDocument(getDocument(), getDocumentLocation()); saveDocument(getDocument(), getDocumentLocation());
} catch (Exception e) { } catch (final Exception e) {
throw new IOException(e); throw new IOException(e);
} }
} }
public void saveDocumentAs(L documentLocation) throws IOException { public void saveDocumentAs(final L documentLocation) throws IOException {
L oldDocumentLocation = getDocumentLocation(); final L oldDocumentLocation = getDocumentLocation();
setDocumentLocation(documentLocation); setDocumentLocation(documentLocation);
try { try {
saveDocument(); saveDocument();
} catch (IOException e) { } catch (final IOException e) {
setDocumentLocation(oldDocumentLocation); setDocumentLocation(oldDocumentLocation);
throw e; throw e;
} }
} }
public void saveCopyAs(L documentLocation) throws Exception { public void saveCopyAs(final L documentLocation) throws Exception {
saveDocument(getDocument(), documentLocation); saveDocument(getDocument(), documentLocation);
} }
} }
...@@ -3,6 +3,17 @@ package tdt4140.gr1800.app.doc; ...@@ -3,6 +3,17 @@ package tdt4140.gr1800.app.doc;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
/**
* An interface with a method for importing domain data from a location.
* The main use is supporting an **import** action in a **File** menu.
* @author hal
*
*/
public interface IDocumentImporter { public interface IDocumentImporter {
/**
* Loads a document from the input stream and sets it as the current document.
* @param inputStream
* @throws IOException
*/
public void importDocument(InputStream inputStream) throws IOException; public void importDocument(InputStream inputStream) throws IOException;
} }
package tdt4140.gr1800.app.doc; package tdt4140.gr1800.app.doc;
/**
* Listener interface for the (contents of) the (current) document of an IDocumentStorage, e.g.
* when an **open** action is performed.
* @author hal
*
* @param <D> the document type
* @param <L> the location type
*/
public interface IDocumentListener<D, L> extends IDocumentStorageListener<L> { public interface IDocumentListener<D, L> extends IDocumentStorageListener<L> {
/**
* Notifies that the current document has changed.
* @param document the new document
* @param oldDocument the previous document
*/
public void documentChanged(D document, D oldDocument); public void documentChanged(D document, D oldDocument);
} }
...@@ -2,6 +2,19 @@ package tdt4140.gr1800.app.doc; ...@@ -2,6 +2,19 @@ package tdt4140.gr1800.app.doc;
import java.io.InputStream; import java.io.InputStream;
/**
* An interface with a method for loading and returning a document (domain data container) from an InputStream.
* This allows various ways of loading or importing domain data, with different sources and formats.
* @author hal
*
* @param <D> the document type
*/
public interface IDocumentLoader<D> { public interface IDocumentLoader<D> {
/**
* Loads and returns a new document from an InputStream
* @param inputStream
* @return
* @throws Exception
*/
public D loadDocument(InputStream inputStream) throws Exception; public D loadDocument(InputStream inputStream) throws Exception;
} }
package tdt4140.gr1800.app.doc; package tdt4140.gr1800.app.doc;
/**
* An interface with a method for saving a document (domain data container) to a location.
* This allows various ways of saving or exporting domain data, to different locations and formats.
* @author hal
*
* @param <D> the document type
* @param <L> the location type
*/
public interface IDocumentSaver<D, L> { public interface IDocumentSaver<D, L> {
/**
* Saves the provided document to the provided location
* @param document
* @param documentLocation
* @throws Exception
*/
public void saveDocument(D document, L documentLocation) throws Exception; public void saveDocument(D document, L documentLocation) throws Exception;
} }
...@@ -3,16 +3,57 @@ package tdt4140.gr1800.app.doc; ...@@ -3,16 +3,57 @@ package tdt4140.gr1800.app.doc;
import java.io.IOException; import java.io.IOException;
import java.util.Collection; import java.util.Collection;
/**
* An interface with the methods necessary for supporting the standard File menu actions.
* The class representing the document (domain data container) is implicit in the implementation of this interface.
* The interface includes methods for getting and setting the location and creating, opening and saving the (current) document.
* @author hal
*
* @param <L> The type of the location, typically java.io.File.
*/
public interface IDocumentStorage<L> { public interface IDocumentStorage<L> {
/**
* Returns the current location (of the current document).
* @return the current location
*/
public L getDocumentLocation(); public L getDocumentLocation();
/**
* Sets the current location (of the current document), can be used by a save-as action.
* @param documentLocation
*/
public void setDocumentLocation(L documentLocation); public void setDocumentLocation(L documentLocation);
/**
* Adds an IDocumentStorageListener that will be notified when the current location changes.
* @param documentStorageListener
*/
public void addDocumentStorageListener(IDocumentStorageListener<L> documentStorageListener); public void addDocumentStorageListener(IDocumentStorageListener<L> documentStorageListener);
/**
* Removes an IDocumentStorageListener.
* @param documentStorageListener
*/
public void removeDocumentStorageListener(IDocumentStorageListener<L> documentStorageListener); public void removeDocumentStorageListener(IDocumentStorageListener<L> documentStorageListener);
/**
* Creates a new documents and sets it as the current one, can be used by a new action.
*/
public void newDocument(); public void newDocument();
/**
* Loads a documents from the provided location and sets it as the current one, can be used by an open action.
*/
public void openDocument(L documentLocation) throws IOException; public void openDocument(L documentLocation) throws IOException;
/**
* Saves the current document (to the current location), can be used by a save action.
*/
public void saveDocument() throws IOException; public void saveDocument() throws IOException;
/**
* Returns the set of IDocumentImporters, can be used by an import action.
* @return
*/
public Collection<IDocumentImporter> getDocumentImporters(); public Collection<IDocumentImporter> getDocumentImporters();
} }
package tdt4140.gr1800.app.doc; package tdt4140.gr1800.app.doc;
/**
* Listener interface for the (current) location of the (current) document of an IDocumentStorage, e.g.
* when a **save-as** action is performed.
* @author hal
*
* @param <L>
*/
public interface IDocumentStorageListener<L> { public interface IDocumentStorageListener<L> {
/**
* Notifies that the current document location has changed.
* @param documentLocation the new document location
* @param oldDocumentLocation the previous document location
*/
public void documentLocationChanged(L documentLocation, L oldDocumentLocation); public void documentLocationChanged(L documentLocation, L oldDocumentLocation);
} }
package tdt4140.gr1800.app.json;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import tdt4140.gr1800.app.core.GeoLocated;
public class GeoLocatedSerializer<T extends GeoLocated> extends StdSerializer<T> {
public static final String LONGITUDE_FIELD_NAME = "longitude";
public static final String LATITUDE_FIELD_NAME = "latitude";
public GeoLocatedSerializer(Class<T> clazz) {
super(clazz);
}
protected void serialize(GeoLocated geoLocated, JsonGenerator jsonGen) throws IOException {
jsonGen.writeFieldName(LATITUDE_FIELD_NAME);
jsonGen.writeNumber(geoLocated.getLatitude());
jsonGen.writeFieldName(LONGITUDE_FIELD_NAME);
jsonGen.writeNumber(geoLocated.getLongitude());
}
@Override
public void serialize(T value, JsonGenerator jsonGen, SerializerProvider provider) throws IOException {
serialize(value, jsonGen);
}
}
package tdt4140.gr1800.app.json;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import tdt4140.gr1800.app.core.GeoLocation;
import tdt4140.gr1800.app.core.GeoLocations;
public class GeoLocationDeserializer extends StdDeserializer<GeoLocation> {
public GeoLocationDeserializer() {
super(GeoLocations.class);
}
@Override
public GeoLocation deserialize(final JsonParser jsonParser, final DeserializationContext deserContext) throws IOException, JsonProcessingException {
final JsonNode jsonNode = jsonParser.getCodec().readTree(jsonParser);
return deserialize(jsonNode);
}
private final TimedTaggedImplDeserializer timedTaggedImplDeserializer = new TimedTaggedImplDeserializer();
private final LatLongDeserializer latLongDeserializer = new LatLongDeserializer();
GeoLocation deserialize(final JsonNode jsonNode) throws JsonProcessingException {
if (jsonNode instanceof ObjectNode) {
final ObjectNode objectNode = (ObjectNode) jsonNode;
final GeoLocation geoLocation = new GeoLocation();
if (objectNode.has(GeoLocationsSerializer.NAME_FIELD_NAME)) {
final String name = objectNode.get(GeoLocationsSerializer.NAME_FIELD_NAME).asText();
geoLocation.setName(name);
}
if (objectNode.has(GeoLocationsSerializer.DESCRIPTION_FIELD_NAME)) {
final String description = objectNode.get(GeoLocationsSerializer.DESCRIPTION_FIELD_NAME).asText();
geoLocation.setDescription(description);
}
if (objectNode.has("location")) {
final JsonNode locationNode = objectNode.get("location");
geoLocation.setLatLong(latLongDeserializer.deserialize(locationNode));
} else {
geoLocation.setLatLong(latLongDeserializer.deserialize(objectNode));
}
if (objectNode.has(GeoLocationSerializer.ELEVATION_FIELD_NAME)) {
final int elevation = objectNode.get(GeoLocationSerializer.ELEVATION_FIELD_NAME).asInt();
geoLocation.setElevation(elevation);
}
timedTaggedImplDeserializer.deserialize(jsonNode, geoLocation);
return geoLocation;
} else if (jsonNode instanceof ArrayNode) {
final GeoLocation geoLocation = new GeoLocation();
geoLocation.setLatLong(latLongDeserializer.deserialize(jsonNode));
return geoLocation;
}
return null;
}
}
package tdt4140.gr1800.app.json;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import tdt4140.gr1800.app.core.GeoLocation;
public class GeoLocationSerializer extends TimedTaggedSerializer<GeoLocation> {
public static final String ELEVATION_FIELD_NAME = "elevation";
public GeoLocationSerializer() {
super(GeoLocation.class);
}
private GeoLocatedSerializer<GeoLocation> geoLocatedSerializer = new GeoLocatedSerializer<>(GeoLocation.class);
@Override
public void serialize(GeoLocation geoLocation, JsonGenerator jsonGen, SerializerProvider serProvider) throws IOException {
jsonGen.writeStartObject();
super.serialize(geoLocation, jsonGen);
geoLocatedSerializer.serialize(geoLocation, jsonGen);
if (geoLocation.getElevation() != 0) {
jsonGen.writeFieldName(ELEVATION_FIELD_NAME);
jsonGen.writeNumber(geoLocation.getElevation());
}
if (geoLocation.getName() != null) {
jsonGen.writeFieldName(GeoLocationsSerializer.NAME_FIELD_NAME);
jsonGen.writeString(geoLocation.getName());
}
if (geoLocation.getDescription() != null) {
jsonGen.writeFieldName(GeoLocationsSerializer.DESCRIPTION_FIELD_NAME);
jsonGen.writeString(geoLocation.getDescription());
}
jsonGen.writeEndObject();
}
}
package tdt4140.gr1800.app.json;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import tdt4140.gr1800.app.core.GeoLocation;
import tdt4140.gr1800.app.core.GeoLocations;
public class GeoLocationsDeserializer extends StdDeserializer<GeoLocations> {
public GeoLocationsDeserializer() {
super(GeoLocations.class);
}
@Override
public GeoLocations deserialize(final JsonParser jsonParser, final DeserializationContext deserContext) throws IOException, JsonProcessingException {
final JsonNode jsonNode = jsonParser.getCodec().readTree(jsonParser);
return deserialize(jsonNode, deserContext);
}
private final GeoLocationDeserializer geoLocationDeserializer = new GeoLocationDeserializer();
GeoLocations deserialize(final JsonNode jsonNode, final DeserializationContext deserContext) throws JsonProcessingException {
if (jsonNode instanceof ObjectNode) {
final ObjectNode objectNode = (ObjectNode) jsonNode;
final String name = objectNode.get(GeoLocationsSerializer.NAME_FIELD_NAME).asText();
final GeoLocations geoLocations = new GeoLocations(name);
final JsonNode pathNode = objectNode.get(GeoLocationsSerializer.PATH_FIELD_NAME);
geoLocations.setPath(pathNode != null && pathNode.asBoolean(false));
final JsonNode locationsNode = objectNode.get(GeoLocationsSerializer.LOCATIONS_FIELD_NAME);
if (locationsNode instanceof ArrayNode) {
for (final JsonNode locationNode : (ArrayNode) locationsNode) {
final GeoLocation geoLocation = geoLocationDeserializer.deserialize(locationNode);
geoLocations.addLocation(geoLocation);
}
}
return geoLocations;
}
return null;
}
}
package tdt4140.gr1800.app.json;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import tdt4140.gr1800.app.core.GeoLocations;
import tdt4140.gr1800.app.core.LatLong;
public class GeoLocationsJsonDeserializer extends StdDeserializer<GeoLocations> {
public GeoLocationsJsonDeserializer() {
super(GeoLocations.class);
}
@Override
public GeoLocations deserialize(JsonParser jsonParser, DeserializationContext deserContext) throws IOException, JsonProcessingException {
JsonNode jsonNode = jsonParser.getCodec().readTree(jsonParser);
return deserialize(jsonNode);
}
private GeoLocations deserialize(JsonNode jsonNode) throws IOException, JsonProcessingException {
if (jsonNode instanceof ObjectNode) {
ObjectNode objectNode = (ObjectNode) jsonNode;
String name = objectNode.get(GeoLocationsJsonSerializer.NAME_FIELD_NAME).asText();
GeoLocations geoLocations = new GeoLocations(name);
JsonNode pathNode = objectNode.get(GeoLocationsJsonSerializer.PATH_FIELD_NAME);
geoLocations.setPath(pathNode != null && pathNode.asBoolean(false));
JsonNode locationsNode = objectNode.get(GeoLocationsJsonSerializer.LOCATIONS_FIELD_NAME);
if (locationsNode instanceof ArrayNode) {
for (JsonNode locationNode : (ArrayNode) locationsNode) {
LatLong latLong = decodeLatLong(locationNode);
geoLocations.addLocation(latLong);
}
} else {
LatLong latLong = decodeLatLong(locationsNode);
geoLocations.addLocation(latLong);
}
return geoLocations;
}
return null;
}
private LatLong decodeLatLong(JsonNode locationNode) {
LatLong latLong = null;
if (locationNode instanceof ObjectNode) {
ObjectNode objectNode = (ObjectNode) locationNode;
if (objectNode.has(GeoLocationsJsonSerializer.LATITUDE_FIELD_NAME) && objectNode.has(GeoLocationsJsonSerializer.LONGITUDE_FIELD_NAME)) {
double lat = objectNode.get(GeoLocationsJsonSerializer.LATITUDE_FIELD_NAME).asDouble();
double lon = objectNode.get(GeoLocationsJsonSerializer.LONGITUDE_FIELD_NAME).asDouble();
latLong = new LatLong(lat, lon);
}
} else if (locationNode instanceof ArrayNode) {
ArrayNode arrayNode = (ArrayNode) locationNode;
if (arrayNode.size() == 2) {
double lat = arrayNode.get(0).asDouble();
double lon = arrayNode.get(1).asDouble();
latLong = new LatLong(lat, lon);
}
}
return latLong;
}
}
...@@ -8,28 +8,37 @@ import java.util.List; ...@@ -8,28 +8,37 @@ import java.util.List;
import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.module.SimpleModule;
import tdt4140.gr1800.app.core.GeoLocation;
import tdt4140.gr1800.app.core.GeoLocations; import tdt4140.gr1800.app.core.GeoLocations;
import tdt4140.gr1800.app.core.GeoLocationsStreamPersistence; import tdt4140.gr1800.app.core.GeoLocationsStreamPersistence;
import tdt4140.gr1800.app.core.LatLong;
import tdt4140.gr1800.app.core.Person;
public class GeoLocationsJsonPersistence implements GeoLocationsStreamPersistence { public class GeoLocationsPersistence implements GeoLocationsStreamPersistence {
private final ObjectMapper objectMapper; private final ObjectMapper objectMapper;
public GeoLocationsJsonPersistence() { public GeoLocationsPersistence() {
objectMapper = new ObjectMapper(); objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule(); final SimpleModule module = new SimpleModule();
module.addSerializer(new GeoLocationsJsonSerializer()); module.addSerializer(new LatLongSerializer());
module.addDeserializer(GeoLocations.class, new GeoLocationsJsonDeserializer()); module.addSerializer(new GeoLocationSerializer());
module.addSerializer(new GeoLocationsSerializer());
module.addSerializer(new PersonSerializer());
module.addDeserializer(LatLong.class, new LatLongDeserializer());
module.addDeserializer(GeoLocation.class, new GeoLocationDeserializer());
module.addDeserializer(GeoLocations.class, new GeoLocationsDeserializer());
module.addDeserializer(Person.class, new PersonDeserializer());
objectMapper.registerModule(module); objectMapper.registerModule(module);
} }
@Override @Override
public Collection<GeoLocations> loadLocations(InputStream inputStream) throws Exception { public Collection<GeoLocations> loadLocations(final InputStream inputStream) throws Exception {
return objectMapper.readValue(inputStream, objectMapper.getTypeFactory().constructCollectionType(List.class, GeoLocations.class)); return objectMapper.readValue(inputStream, objectMapper.getTypeFactory().constructCollectionType(List.class, GeoLocations.class));
} }
@Override @Override
public void saveLocations(Collection<GeoLocations> geoLocations, OutputStream outputStream) throws Exception { public void saveLocations(final Collection<GeoLocations> geoLocations, final OutputStream outputStream) throws Exception {
objectMapper.writeValue(outputStream, geoLocations); objectMapper.writeValue(outputStream, geoLocations);
} }
} }
...@@ -9,34 +9,37 @@ import com.fasterxml.jackson.databind.ser.std.StdSerializer; ...@@ -9,34 +9,37 @@ import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import tdt4140.gr1800.app.core.GeoLocated; import tdt4140.gr1800.app.core.GeoLocated;
import tdt4140.gr1800.app.core.GeoLocations; import tdt4140.gr1800.app.core.GeoLocations;
public class GeoLocationsJsonSerializer extends StdSerializer<GeoLocations> { public class GeoLocationsSerializer extends StdSerializer<GeoLocations> {
public static final String LONGITUDE_FIELD_NAME = "longitude";
public static final String LATITUDE_FIELD_NAME = "latitude";
public static final String LOCATIONS_FIELD_NAME = "locations"; public static final String LOCATIONS_FIELD_NAME = "locations";
public static final String PATH_FIELD_NAME = "path"; public static final String PATH_FIELD_NAME = "path";
public static final String NAME_FIELD_NAME = "name"; public static final String NAME_FIELD_NAME = "name";
public static final String DESCRIPTION_FIELD_NAME = "description";
public GeoLocationsJsonSerializer() { public GeoLocationsSerializer() {
super(GeoLocations.class); super(GeoLocations.class);
} }
private TimedTaggedSerializer<GeoLocations> timedTaggedSerializer = new TimedTaggedSerializer<>(GeoLocations.class);
@Override @Override
public void serialize(GeoLocations geoLocations, JsonGenerator jsonGen, SerializerProvider serProvider) throws IOException { public void serialize(GeoLocations geoLocations, JsonGenerator jsonGen, SerializerProvider serProvider) throws IOException {
jsonGen.writeStartObject(); jsonGen.writeStartObject();
jsonGen.writeFieldName(NAME_FIELD_NAME); jsonGen.writeFieldName(NAME_FIELD_NAME);
jsonGen.writeString(geoLocations.getName()); jsonGen.writeString(geoLocations.getName());
if (geoLocations.getDescription() != null) {
jsonGen.writeFieldName(DESCRIPTION_FIELD_NAME);
jsonGen.writeString(geoLocations.getDescription());
}
jsonGen.writeFieldName(PATH_FIELD_NAME); jsonGen.writeFieldName(PATH_FIELD_NAME);
jsonGen.writeBoolean(geoLocations.isPath()); jsonGen.writeBoolean(geoLocations.isPath());
jsonGen.writeFieldName(LOCATIONS_FIELD_NAME); jsonGen.writeFieldName(LOCATIONS_FIELD_NAME);
jsonGen.writeStartArray(); jsonGen.writeStartArray();
for (GeoLocated geoLoc : geoLocations) { for (GeoLocated geoLoc : geoLocations) {
jsonGen.writeStartArray(); jsonGen.writeObject(geoLoc);
jsonGen.writeNumber(geoLoc.getLatitude());
jsonGen.writeNumber(geoLoc.getLongitude());
jsonGen.writeEndArray();
} }
jsonGen.writeEndArray(); jsonGen.writeEndArray();
timedTaggedSerializer.serialize(geoLocations, jsonGen);
jsonGen.writeEndObject(); jsonGen.writeEndObject();
} }
} }
package tdt4140.gr1800.app.json;
import java.util.function.Consumer;
import java.util.function.Function;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.node.ObjectNode;
public abstract class IdDeserializer<T> extends StdDeserializer<T> {
public IdDeserializer(final Class<T> clazz) {
super(clazz);
}
void deserialize(final ObjectNode objectNode, final String fieldName, final Consumer<String> setter) throws JsonProcessingException {
if (objectNode.has(fieldName)) {
final String s = objectNode.get(fieldName).asText();
setter.accept(s);
}
}
<U> void deserialize(final ObjectNode objectNode, final String fieldName, final Function<String, U> parser, final Consumer<U> setter) throws JsonProcessingException {
if (objectNode.has(fieldName)) {
final String s = objectNode.get(fieldName).asText();
final U value = parser.apply(s);
setter.accept(value);
}
}
}