org.openstreetmap.josm.plugins.openstreetcam.service.photo.OpenStreetCamService.java Source code

Java tutorial

Introduction

Here is the source code for org.openstreetmap.josm.plugins.openstreetcam.service.photo.OpenStreetCamService.java

Source

/*
 * The code is licensed under the LGPL Version 3 license http://www.gnu.org/licenses/lgpl-3.0.en.html.
 *
 * The collected imagery is protected & available under the CC BY-SA version 4 International license.
 * https://creativecommons.org/licenses/by-sa/4.0/legalcode.
 *
 * Copyright (c)2017, Telenav, Inc. All Rights Reserved
 */
package org.openstreetmap.josm.plugins.openstreetcam.service.photo;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import org.openstreetmap.josm.plugins.openstreetcam.entity.Photo;
import org.openstreetmap.josm.plugins.openstreetcam.entity.PhotoDataSet;
import org.openstreetmap.josm.plugins.openstreetcam.entity.Segment;
import org.openstreetmap.josm.plugins.openstreetcam.entity.Sequence;
import org.openstreetmap.josm.plugins.openstreetcam.service.BaseService;
import org.openstreetmap.josm.plugins.openstreetcam.service.ServiceException;
import org.openstreetmap.josm.plugins.openstreetcam.service.photo.adapter.PhotoTypeAdapter;
import org.openstreetmap.josm.plugins.openstreetcam.service.photo.adapter.SegmentTypeAdapter;
import org.openstreetmap.josm.plugins.openstreetcam.service.photo.entity.ListResponse;
import org.openstreetmap.josm.plugins.openstreetcam.service.photo.entity.PhotoDetailsResponse;
import org.openstreetmap.josm.plugins.openstreetcam.service.photo.entity.SequencePhotoListResponse;
import org.openstreetmap.josm.plugins.openstreetcam.util.cnf.OpenStreetCamServiceConfig;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.telenav.josm.common.argument.BoundingBox;
import com.telenav.josm.common.http.HttpConnector;
import com.telenav.josm.common.http.HttpConnectorException;

/**
 * Executes the operations of the OpenStreetCam service.
 *
 * @author Beata
 * @version $Revision$
 */
public class OpenStreetCamService extends BaseService {

    private static final int SECOND_PAGE = 2;

    @Override
    public Gson createGson() {
        final GsonBuilder builder = new GsonBuilder();
        builder.serializeNulls();
        builder.registerTypeAdapter(Photo.class, new PhotoTypeAdapter());
        builder.registerTypeAdapter(Segment.class, new SegmentTypeAdapter());
        return builder.create();
    }

    /**
     * Retrieves OpenStreetCam photos from the given area based on the specified filters.
     *
     * @param area a {@code BoundingBox} defines the searching area
     * @param date a {@code Date} if not null, then the method returns the photos that were uploaded after the specified
     * date
     * @param osmUserId a {@code Long} specifies the user's OSM identifier; if not null return only the photos that were
     * uploaded by the logged in user
     * @param paging a {@code Paging} represents the pagination for the data set
     * @return a list of {@code Photo}s
     * @throws ServiceException if the operation fails
     */
    public PhotoDataSet listNearbyPhotos(final BoundingBox area, final Date date, final Long osmUserId,
            final Paging paging) throws ServiceException {
        final Map<String, String> arguments = new HttpContentBuilder(area, date, osmUserId, paging).getContent();
        final String url = OpenStreetCamServiceConfig.getInstance().getServiceUrl()
                .concat(RequestConstants.LIST_NEARBY_PHOTOS);
        final ListResponse<Photo> listPhotoResponse = executePost(url, arguments,
                new TypeToken<ListResponse<Photo>>() {
                }.getType());
        verifyResponseStatus(listPhotoResponse);
        return listPhotoResponse != null
                ? new PhotoDataSet(listPhotoResponse.getCurrentPageItems(), paging.getPage(),
                        listPhotoResponse.getTotalItems())
                : new PhotoDataSet();
    }

    /**
     * Retrieves the sequence associated with the given identifier.
     *
     * @param id a sequence identifier
     * @return a {@code Sequence} that contains all the photos that belongs to the sequence
     * @throws ServiceException if the operation fails
     */
    public Sequence retrieveSequence(final Long id) throws ServiceException {
        final Map<String, String> arguments = new HttpContentBuilder(id).getContent();
        final String url = OpenStreetCamServiceConfig.getInstance().getServiceUrl()
                .concat(RequestConstants.SEQUENCE_PHOTO_LIST);
        final SequencePhotoListResponse detailsResponse = executePost(url, arguments,
                SequencePhotoListResponse.class);
        verifyResponseStatus(detailsResponse);

        Sequence sequence = null;
        if (detailsResponse != null) {
            sequence = detailsResponse.getOsv();

            // order photos by sequence index
            sequence.getPhotos().sort(Comparator.comparing(Photo::getSequenceIndex));
        }
        return sequence;
    }

    /**
     * Retrieves the photo with the given name.
     *
     * @param photoName represents the full name (contains also the path) of an image
     * @return the photo in byte format
     * @throws ServiceException if the operation failed
     */
    public byte[] retrievePhoto(final String photoName) throws ServiceException {
        final String url = OpenStreetCamServiceConfig.getInstance().getServiceBaseUrl().concat(photoName);
        byte[] image;
        try {
            final HttpConnector connector = new HttpConnector(url, getHeaders());
            image = connector.getBytes();
        } catch (final HttpConnectorException e) {
            throw new ServiceException(e);
        }
        return image;
    }

    /**
     * Returns a list of segments that has OpenStreetCam coverage from the given area.
     *
     * @param area a {@code BoundingBox} represents the current area
     * @param osmUserId a {@code Long} specifies the user's OSM identifier; if not null return only the photos that were
     * uploaded by the logged in user
     * @param zoom represents the current zoom level
     * @return a list of {@code Segment}s
     * @throws ServiceException if the operation fails
     */
    public List<Segment> listMatchedTracks(final BoundingBox area, final Long osmUserId, final int zoom)
            throws ServiceException {
        final ListResponse<Segment> listSegmentResponse = listMatchedTacks(area, osmUserId, zoom,
                Paging.TRACKS_DEFAULT);
        final Set<Segment> segments = new HashSet<>();
        if (listSegmentResponse != null) {
            segments.addAll(listSegmentResponse.getCurrentPageItems());
            if (listSegmentResponse.getTotalItems() > OpenStreetCamServiceConfig.getInstance()
                    .getTracksMaxItems()) {
                final int pages = listSegmentResponse.getTotalItems() > OpenStreetCamServiceConfig.getInstance()
                        .getTracksMaxItems()
                                ? (listSegmentResponse.getTotalItems()
                                        / OpenStreetCamServiceConfig.getInstance().getTracksMaxItems()) + 1
                                : SECOND_PAGE;
                final ExecutorService executor = Executors.newFixedThreadPool(pages);
                final List<Future<ListResponse<Segment>>> futures = new ArrayList<>();
                for (int i = SECOND_PAGE; i <= pages; i++) {
                    final Paging paging = new Paging(i,
                            OpenStreetCamServiceConfig.getInstance().getTracksMaxItems());
                    final Callable<ListResponse<Segment>> callable = () -> listMatchedTacks(area, osmUserId, zoom,
                            paging);
                    futures.add(executor.submit(callable));
                }
                segments.addAll(readResult(futures));
                executor.shutdown();
            }
        }
        return new ArrayList<>(segments);
    }

    private ListResponse<Segment> listMatchedTacks(final BoundingBox area, final Long osmUserId, final int zoom,
            final Paging paging) throws ServiceException {
        final Map<String, String> arguments = new HttpContentBuilder(area, osmUserId, zoom, paging).getContent();
        final String url = OpenStreetCamServiceConfig.getInstance().getServiceBaseUrl()
                .concat(RequestConstants.LIST_MATCHED_TRACKS);
        final ListResponse<Segment> listSegmentResponse = executePost(url, arguments,
                new TypeToken<ListResponse<Segment>>() {
                }.getType());
        verifyResponseStatus(listSegmentResponse);
        return listSegmentResponse;
    }

    public Photo retrievePhotoDetails(final Long sequenceId, final Integer sequenceIndex) throws ServiceException {
        final Map<String, String> arguments = new HttpContentBuilder(sequenceId, sequenceIndex).getContent();
        final String url = OpenStreetCamServiceConfig.getInstance().getServiceUrl()
                .concat(RequestConstants.PHOTO_DETAILS);
        final PhotoDetailsResponse result = executePost(url, arguments, PhotoDetailsResponse.class);
        verifyResponseStatus(result);
        return result != null && result.getOsv() != null ? result.getOsv().getPhotoObject() : null;
    }
}