Skip to content
Snippets Groups Projects
Commit f208d6ff authored by Mads Lundegaard's avatar Mads Lundegaard
Browse files

Merge branch 'refactor/map-markers' into 'dev'

Add infowindows to markers

See merge request !155
parents e1e1813d a06d16af
No related branches found
No related tags found
2 merge requests!165Weekly merge to Master,!155Add infowindows to markers
Pipeline #80943 failed
......@@ -2,55 +2,65 @@ package NTNU.IDATT1002.controllers;
import NTNU.IDATT1002.models.GeoLocation;
import NTNU.IDATT1002.models.Image;
import NTNU.IDATT1002.service.TagService;
import NTNU.IDATT1002.utils.MetadataStringFormatter;
import com.lynden.gmapsfx.GoogleMapView;
import com.lynden.gmapsfx.javascript.event.UIEventType;
import com.lynden.gmapsfx.javascript.object.*;
import netscape.javascript.JSObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* Class ImageMapFactory. Factory for map creation with markers for given images and default options.
* Default center location is Berlin in order to center the full scale map onto a page.
* Default center location is Copenhagen in order to center the full scale map onto a page.
*
* @author Eirik Steira
*/
public class ImageMapFactory {
private static Logger logger = LoggerFactory.getLogger(ImageMapFactory.class);
private ImageMapFactory() {}
private GoogleMap map;
private Logger logger = LoggerFactory.getLogger(ImageMapFactory.class);
private Map<LatLong, Image> latLongImageMapping = new HashMap<>();
public ImageMapFactory() {
}
/**
* Create a map from given {@link GoogleMapView} with default options.
*
* @param googleMapView the map view to add the map to
* @param mapView the map view to add the map to
* @return the {@link GoogleMap} created to enable further customization
*/
public static GoogleMap createMap(GoogleMapView googleMapView) {
public GoogleMap createMap(GoogleMapView mapView) {
MapOptions mapOptions = getMapOptions();
return googleMapView.createMap(mapOptions);
map = mapView.createMap(mapOptions);
logger.info("[x] Map created");
return map;
}
/**
* Create default {@link MapOptions} to be applied to a map. Extend this for further marker customizations.
* The default center location is Berlin to get a look of the entire map when the zoom is set to fit the window.
* The default center location is Copenhagen to get a look of the entire map when the zoom is set to fit the window.
*
* @return the default map options
*/
private static MapOptions getMapOptions() {
LatLong berlin = new LatLong(52.520008, 13.404954);
private MapOptions getMapOptions() {
LatLong copenhagen = new LatLong(55.676098, 12.568337);
return new MapOptions()
.center(berlin)
.center(copenhagen)
.mapType(MapTypeIdEnum.ROADMAP)
.overviewMapControl(false)
.panControl(false)
.rotateControl(false)
.scaleControl(false)
.streetViewControl(false)
.zoomControl(false)
.zoomControl(true)
.zoom(3);
}
......@@ -60,7 +70,7 @@ public class ImageMapFactory {
* @param images the list of images
* @return a list of markers created from the images
*/
public static List<Marker> createMarkers(List<Image> images) {
public List<Marker> createMarkers(List<Image> images) {
List<LatLong> locations = getLatLongs(images);
List<Marker> markers = getMarkers(locations);
logger.info("[x] {} markers created", markers.size());
......@@ -73,16 +83,27 @@ public class ImageMapFactory {
* @param images the list of images
* @return a list of {@link LatLong}
*/
private static List<LatLong> getLatLongs(List<Image> images) {
private List<LatLong> getLatLongs(List<Image> images) {
return images.stream()
.map(Image::getGeoLocation)
.filter(GeoLocation::hasLatLong)
.map(geoLocation -> {
double latitude = Double.parseDouble(geoLocation.getLatitude());
double longitude = Double.parseDouble(geoLocation.getLongitude());
return new LatLong(latitude, longitude);
})
.collect(Collectors.toList());
.filter(image -> image.getGeoLocation().hasLatLong())
.map(image -> {
LatLong latLong = getLatLong(image);
latLongImageMapping.put(latLong, image);
return latLong;
}).collect(Collectors.toList());
}
/**
* Get a {@link LatLong} from a single image.
*
* @param image the image holding the {@link GeoLocation}
* @return the {@link LatLong} created
*/
private LatLong getLatLong(Image image) {
GeoLocation geoLocation = image.getGeoLocation();
double latitude = Double.parseDouble(geoLocation.getLatitude());
double longitude = Double.parseDouble(geoLocation.getLongitude());
return new LatLong(latitude, longitude);
}
/**
......@@ -91,15 +112,58 @@ public class ImageMapFactory {
* @param locations the list containing the locations
* @return the list of markers created
*/
private static List<Marker> getMarkers(List<LatLong> locations) {
private List<Marker> getMarkers(List<LatLong> locations) {
return locations.stream()
.map(location -> {
MarkerOptions markerOptions = new MarkerOptions()
.position(location);
logger.info("[x] Marker created for location: {}", location);
return new Marker(markerOptions);
})
.map(this::getMarker)
.collect(Collectors.toList());
}
/**
* Create {@link Marker} for given location with map zoom and center on click event.
*
* @param location the location of the marker
* @return marker created
*/
private Marker getMarker(LatLong location) {
MarkerOptions markerOptions = new MarkerOptions()
.position(location)
.animation(Animation.DROP);
logger.info("[x] Marker created for location: {}", location);
Marker marker = new Marker(markerOptions);
InfoWindow infoWindow = getInfoWindow(location);
map.addUIEventHandler(marker, UIEventType.click, (JSObject obj) -> {
map.setZoom(10);
map.setCenter(location);
infoWindow.open(map, marker);
});
return marker;
}
/**
* Get {@link InfoWindow} with default options to display the
* corresponding image data.
*
* @param location the location corresponding to an image
* @return the {@link InfoWindow} created
*/
private InfoWindow getInfoWindow(LatLong location) {
Image image = latLongImageMapping.get(location);
String username = image.getUser().getUsername();
String tags = TagService.getTagsAsString(image.getTags());
Date uploadedAt = image.getUploadedAt();
String metadata = MetadataStringFormatter.format(image.getMetadata(), "<br/>");
InfoWindowOptions infoWindowOptions = new InfoWindowOptions()
.content("<h3>Id: " + image.getId() + "</h3>" +
"<p><b>User:</b> " + username + "</p>" +
"<p><b>Tags:</b> " + tags + "</p>" +
"<p><b>Uploaded at:</b> " + uploadedAt + "</p>" +
"<p><b>Metadata:</b> <br/>" + metadata + "</p>");
return new InfoWindow(infoWindowOptions);
}
}
......@@ -102,14 +102,15 @@ public class Map extends NavBarController implements Initializable, MapComponent
*/
@Override
public void mapInitialized() {
googleMap = ImageMapFactory.createMap(mapView);
ImageMapFactory imageMapFactory = new ImageMapFactory();
googleMap = imageMapFactory.createMap(mapView);
Task<List<Image>> fetchImagesTask = getImageListTask();
executorService.submit(fetchImagesTask);
fetchImagesTask.setOnSucceeded(workerStateEvent -> {
List<Image> images = fetchImagesTask.getValue();
List<Marker> markers = ImageMapFactory.createMarkers(images);
List<Marker> markers = imageMapFactory.createMarkers(images);
googleMap.addMarkers(markers);
});
}
......
......@@ -116,11 +116,10 @@ public class Image {
return uploadedAt;
}
public String getPath() {
return path;
public User getUser() {
return user;
}
/**
* Add this image in the given album.
*
......
......@@ -61,6 +61,22 @@ public class Metadata {
public Metadata() {
}
public Metadata(Metadata metadata) {
this.metadataId = metadata.getMetadataId();
this.image = metadata.getImage();
this.geolocation = metadata.getGeoLocation();
this.camera = metadata.getCamera();
this.lens = metadata.getLens();
this.aperture = metadata.getAperture();
this.shutterSpeed = metadata.getShutterSpeed();
this.ISO = metadata.getISO();
this.focalLength = metadata.getFocalLength();
this.fileType = metadata.getFileType();
this.photoDate = metadata.getPhotoDate();
this.fileSize = metadata.getFileSize();
this.fileDimension = metadata.getFileDimension();
}
public Long getMetadataId() {
return metadataId;
......
package NTNU.IDATT1002.utils;
import NTNU.IDATT1002.models.GeoLocation;
import NTNU.IDATT1002.models.Metadata;
import org.apache.commons.text.WordUtils;
import org.slf4j.Logger;
......@@ -38,14 +39,15 @@ public class MetadataStringFormatter {
* @param delimiter the delimiter separating the fields
* @return the formatted string
*/
public static String format(Metadata metadata, char delimiter) {
public static String format(Metadata metadata, String delimiter) {
Metadata pureMetadata = new Metadata(metadata);
Stream<Field> fields = Arrays.stream(pureMetadata.getClass().getDeclaredFields());
Stream<Field> fields = Arrays.stream(metadata.getClass().getDeclaredFields());
StringBuilder metadataString = new StringBuilder();
fields.filter(field -> include.contains(field.getName()))
.forEach(field -> {
String formattedField = getFormattedField(metadata, delimiter, field);
String formattedField = getFormattedField(pureMetadata, delimiter, field);
metadataString.append(formattedField);
});
......@@ -63,21 +65,17 @@ public class MetadataStringFormatter {
* @return the formatted field as a string
*/
private static String getFormattedField(Metadata metadata,
char delimiter,
String delimiter,
Field field) {
field.setAccessible(true);
String[] fieldNameSplitByUppercase = field.getName().split("(?=\\p{Upper}[a-z])");
String fieldNameTitle = String.join(" ", fieldNameSplitByUppercase);
StringBuilder fieldString = new StringBuilder();
fieldString.append(WordUtils.capitalizeFully(fieldNameTitle))
.append(": ");
fieldString.append(getFieldValue(metadata, field))
.append(delimiter);
return fieldString.toString();
return WordUtils.capitalizeFully(fieldNameTitle) +
": " +
getFieldValue(metadata, field) +
delimiter;
}
/**
......@@ -88,14 +86,9 @@ public class MetadataStringFormatter {
*/
private static String getFieldValue(Metadata metadata, Field field) {
StringBuilder fieldValueString = new StringBuilder();
try {
if (field.get(metadata) == null)
fieldValueString.append("No ")
.append(field.getName())
.append(" found.");
else
fieldValueString.append(field.get(metadata));
appendFieldValue(metadata, field, fieldValueString);
} catch (IllegalAccessException e) {
logger.error("[x] Failed to process field {}", field.getName(), e);
}
......@@ -103,4 +96,34 @@ public class MetadataStringFormatter {
return fieldValueString.toString();
}
/**
* Append given fields value from given metadata to given string builder.
*
* @param metadata the metadata object holding the data
* @param field the field to get the value from
* @param fieldValueString the StringBuilder to append to
* @throws IllegalAccessException if field does not exist or access is denied
*/
private static void appendFieldValue(Metadata metadata, Field field, StringBuilder fieldValueString)
throws IllegalAccessException {
Object fieldValue = field.get(metadata);
if (fieldValue == null || fieldValue.equals(""))
fieldValueString.append("No ")
.append(field.getName())
.append(" found.");
else if (field.getName().equals("geolocation"))
fieldValueString.append(getGeoLocationValue(metadata, field));
else
fieldValueString.append(fieldValue);
}
private static String getGeoLocationValue(Metadata metadata, Field field) throws IllegalAccessException {
GeoLocation geolocation = (GeoLocation) field.get(metadata);
return "latitude: " +
geolocation.getLatitude() +
", longitude: " +
geolocation.getLatitude();
}
}
......@@ -76,7 +76,7 @@
<AnchorPane minHeight="0.0" minWidth="0.0" prefHeight="797.0" prefWidth="1920.0" style="-fx-background-color: #888888;" VBox.vgrow="ALWAYS">
<children>
<GoogleMapView fx:id="mapView" prefHeight="750.0" prefWidth="761.0" AnchorPane.bottomAnchor="-185.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="-441.0" AnchorPane.topAnchor="0.0"/>
<GoogleMapView fx:id="mapView" prefHeight="750.0" prefWidth="761.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0"/>
</children>
</AnchorPane>
......
......@@ -27,7 +27,7 @@ class MetadataStringFormatterTest {
@Disabled("Not able to solve CI test run failure on this test")
@Test
void testFormatReturnsFormattedString() {
String metadataString = MetadataStringFormatter.format(metadata, ' ');
String metadataString = MetadataStringFormatter.format(metadata, "");
assertEquals(metadataString.trim(), formattedMetadata.trim());
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment