/*
* Copyright 2013, L. Murer.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see < http://www.gnu.org/licenses/ >.
*/
package models;
import de.schildbach.pte.dto.Location;
import play.Logger;
import javax.validation.constraints.NotNull;
import java.util.*;
/**
* Created by IntelliJ IDEA.
* User: Laurin
* Date: 08.11.11
* Time: 12:08
*/
public class PopularLocation implements Comparable<PopularLocation> {
// private String provider;
//The popularity this location has (the higher the better)
private int popularity = 0;
//The location this represents
private final Location location;
//all popular Locations by Provider and by ID (First key: ID of the Provider; second Key: ID of the location
private static final HashMap<String, Map<Integer, PopularLocation>> byID = new HashMap<>();
/**
* @param provider The ID of the provider this location belongs to
* @param location A location to represent with a popularity
*/
private PopularLocation(String provider, Location location) {
this.location = location;
// this.provider = provider;
if (location.hasId()) {
Map<Integer, PopularLocation> providers_list = getProvidersList(provider);
providers_list.put(location.id, this);
}
}
/**
* Increase the popularity for this location by one
*/
private void increasePopularity() {
if (popularity < Integer.MAX_VALUE) {
popularity++;
}
}
/**
* Returns a popular location object (a new one or one already counting for)
*
* @param provider a provider for whom it is
* @param location a location to find the PopularLocation-Object for
* @return a new or an already generated PopularLocation-Object for the given location
*/
private static PopularLocation get(@NotNull String provider, @NotNull Location location) {
Map<Integer, PopularLocation> providers_list = getProvidersList(provider);
PopularLocation pl = providers_list.get(location.id);
if (pl == null) {
pl = new PopularLocation(provider, location);
}
if (!pl.location.name.equals(location.name)) {
Logger.warn("Multiple locations with id " + location.id + " (" + pl.location.name + " and " + location.name + ")");
}
return pl;
}
/**
* Returns the list of the already generated PopularLocations for a given provider
*
* @param provider the provider for whom the list is requested
* @return A map (Location-Key -> PopularLocation) for the given provider
*/
private static Map<Integer, PopularLocation> getProvidersList(String provider) {
Map<Integer, PopularLocation> providers_list = byID.get(provider);
if (providers_list == null) {
providers_list = new HashMap<>();
byID.put(provider, providers_list);
}
return providers_list;
}
/**
* Returns a list of Locations (their name for the user) for a given search term
*
* @param provider For which the request is done
* @param term The term that is looked up
* @param maximum A maximum amount of return values
* @return popular locations (max the amount given) for the given term
*/
public static List<String> getMostPopularLike(String provider, String term, int maximum) {
if (term == null) {
return new ArrayList<>(0);
}
TreeSet<PopularLocation> top = new TreeSet<>();
for (PopularLocation pl : getProvidersList(provider).values()) {
if (pl.location.name.contains(term)) {
top.add(pl);
}
}
int values = Math.min(maximum, top.size());
List<String> ret = new ArrayList<>(values);
Iterator<PopularLocation> popularLocationIterator = top.iterator();
while (values-- > 0) {
ret.add(popularLocationIterator.next().location.name);
}
return ret;
}
/**
* Compares the popularity of two locations
*
* @param popularLocation the other PopularLocation Object
* @return a positive number if this is more popular
*/
public int compareTo(PopularLocation popularLocation) {
int popularityDifference = popularLocation.popularity - popularity;
if (popularityDifference != 0) {
return popularityDifference;
} else {
return hashCode() - popularLocation.hashCode();
}
}
/**
* Increases the popularity for some locations by one
*
* @param provider the provider to whom the locations belong
* @param ls the locations for which the popularity will be increased
*/
public static void increasePopularities(String provider, Collection<Location> ls) {
for (Location l : ls) {
if (l != null) {
get(provider, l).increasePopularity();
}
}
}
}