Improved JNI for Booking filter

This commit is contained in:
r.kuznetsov 2017-12-01 14:05:46 +03:00 committed by Aleksandr Zatsepin
parent 06e1ccec2a
commit eeee2b2165
9 changed files with 136 additions and 19 deletions

View file

@ -1,5 +1,6 @@
#include "com/mapswithme/maps/SearchEngine.hpp"
#include "com/mapswithme/maps/Framework.hpp"
#include "com/mapswithme/maps/UserMarkHelper.hpp"
#include "com/mapswithme/platform/Platform.hpp"
#include "map/everywhere_search_params.hpp"
@ -316,6 +317,8 @@ uint64_t g_queryTimestamp;
jobject g_javaListener;
jmethodID g_updateResultsId;
jmethodID g_endResultsId;
// Implements 'NativeBookingFilterListener' java interface.
jmethodID g_onFilterAvailableHotelsId;
// Cached classes and methods to return results.
jclass g_resultClass;
jmethodID g_resultConstructor;
@ -328,6 +331,8 @@ jmethodID g_mapResultsMethod;
jclass g_mapResultClass;
jmethodID g_mapResultCtor;
booking::AvailabilityParams g_lastBookingFilterParams;
jobject ToJavaResult(Result & result, bool isLocalAdsCustomer, bool hasPosition, double lat,
double lon)
{
@ -365,6 +370,7 @@ jobject ToJavaResult(Result & result, bool isLocalAdsCustomer, bool hasPosition,
return ret;
}
jni::TScopedLocalRef featureId(env, usermark_helper::CreateFeatureId(env, result.GetFeatureID()));
jni::TScopedLocalRef featureType(env, jni::ToJavaString(env, result.GetFeatureType()));
jni::TScopedLocalRef address(env, jni::ToJavaString(env, result.GetAddress()));
jni::TScopedLocalRef dist(env, jni::ToJavaString(env, distance));
@ -372,7 +378,7 @@ jobject ToJavaResult(Result & result, bool isLocalAdsCustomer, bool hasPosition,
jni::TScopedLocalRef rating(env, jni::ToJavaString(env, result.GetHotelRating()));
jni::TScopedLocalRef pricing(env, jni::ToJavaString(env, result.GetHotelApproximatePricing()));
jni::TScopedLocalRef desc(env, env->NewObject(g_descriptionClass, g_descriptionConstructor,
featureType.get(), address.get(),
featureId.get(), featureType.get(), address.get(),
dist.get(), cuisine.get(),
rating.get(), pricing.get(),
result.GetStarsCount(),
@ -437,7 +443,21 @@ void OnMapSearchResults(storage::DownloaderSearchResults const & results, long l
JNIEnv * env = jni::GetEnv();
jni::TScopedLocalObjectArrayRef jResults(env, BuildJavaMapResults(results.m_results));
env->CallVoidMethod(g_javaListener, g_mapResultsMethod, jResults.get(), static_cast<jlong>(timestamp), results.m_endMarker);
env->CallVoidMethod(g_javaListener, g_mapResultsMethod, jResults.get(),
static_cast<jlong>(timestamp), results.m_endMarker);
}
void OnBookingFilterResults(booking::AvailabilityParams const & params,
std::vector<FeatureID> const & featuresSorted)
{
// Ignore obsolete booking filter results.
if (params != g_lastBookingFilterParams)
return;
JNIEnv * env = jni::GetEnv();
jni::TScopedLocalObjectArrayRef jResults(env,
usermark_helper::ToFeatureIdArray(env, featuresSorted));
env->CallVoidMethod(g_javaListener, g_onFilterAvailableHotelsId, jResults.get());
}
} // namespace
@ -476,25 +496,37 @@ extern "C"
"(Ljava/lang/String;Lcom/mapswithme/maps/search/SearchResult$Description;DD[IZZ)V");
g_suggestConstructor = jni::GetConstructorID(env, g_resultClass, "(Ljava/lang/String;Ljava/lang/String;DD[I)V");
g_descriptionClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/search/SearchResult$Description");
g_descriptionConstructor = jni::GetConstructorID(env, g_descriptionClass, "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;II)V");
g_descriptionConstructor = jni::GetConstructorID(env, g_descriptionClass,
"(Lcom/mapswithme/maps/bookmarks/data/FeatureId;"
"Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;"
"Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;II)V");
g_mapResultsMethod = jni::GetMethodID(env, g_javaListener, "onMapSearchResults", "([Lcom/mapswithme/maps/search/NativeMapSearchListener$Result;JZ)V");
g_mapResultsMethod = jni::GetMethodID(env, g_javaListener, "onMapSearchResults",
"([Lcom/mapswithme/maps/search/NativeMapSearchListener$Result;JZ)V");
g_mapResultClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/search/NativeMapSearchListener$Result");
g_mapResultCtor = jni::GetConstructorID(env, g_mapResultClass, "(Ljava/lang/String;Ljava/lang/String;)V");
g_onFilterAvailableHotelsId = jni::GetMethodID(env, g_javaListener, "onFilterAvailableHotels",
"([Lcom/mapswithme/maps/bookmarks/data/FeatureId;)V");
g_hotelsFilterBuilder.Init(env);
g_bookingAvailabilityParamsBuilder.Init(env);
}
JNIEXPORT jboolean JNICALL Java_com_mapswithme_maps_search_SearchEngine_nativeRunSearch(
JNIEnv * env, jclass clazz, jbyteArray bytes, jstring lang, jlong timestamp,
jboolean hasPosition, jdouble lat, jdouble lon, jobject hotelsFilter)
jboolean hasPosition, jdouble lat, jdouble lon, jobject hotelsFilter,
jobject bookingFilterParams)
{
search::EverywhereSearchParams params;
params.m_query = jni::ToNativeString(env, bytes);
params.m_inputLocale = jni::ToNativeString(env, lang);
params.m_onResults = bind(&OnResults, _1, _2, timestamp, false, hasPosition, lat, lon);
params.m_hotelsFilter = g_hotelsFilterBuilder.Build(env, hotelsFilter);
g_lastBookingFilterParams = g_bookingAvailabilityParamsBuilder.Build(env, bookingFilterParams);
params.m_bookingFilterParams.m_params = g_lastBookingFilterParams;
params.m_bookingFilterParams.m_callback = std::bind(&OnBookingFilterResults, _1, _2);
bool const searchStarted = g_framework->NativeFramework()->SearchEverywhere(params);
if (searchStarted)
@ -510,8 +542,9 @@ extern "C"
vparams.m_query = jni::ToNativeString(env, bytes);
vparams.m_inputLocale = jni::ToNativeString(env, lang);
vparams.m_hotelsFilter = g_hotelsFilterBuilder.Build(env, hotelsFilter);
vparams.m_bookingFilterParams.m_params =
g_bookingAvailabilityParamsBuilder.Build(env, bookingFilterParams);
g_lastBookingFilterParams = g_bookingAvailabilityParamsBuilder.Build(env, bookingFilterParams);
vparams.m_bookingFilterParams.m_params = g_lastBookingFilterParams;
vparams.m_bookingFilterParams.m_callback = std::bind(&OnBookingFilterResults, _1, _2);
// TODO (@alexzatsepin): set up vparams.m_onCompleted here and use
// HotelsClassifier for hotel queries detection.

View file

@ -240,4 +240,27 @@ jobject CreateRoutePointInfo(JNIEnv * env, place_page::Info const & info)
int const markType = static_cast<int>(info.GetRouteMarkType());
return env->NewObject(clazz, ctorId, markType, info.GetIntermediateIndex());
}
jobject CreateFeatureId(JNIEnv * env, FeatureID const & fid)
{
static jmethodID const featureCtorId =
jni::GetConstructorID(env, g_featureIdClazz, "(Ljava/lang/String;JI)V");
auto const & info = fid.m_mwmId.GetInfo();
jni::TScopedLocalRef jMwmName(env, jni::ToJavaString(env, info ? info->GetCountryName() : ""));
return env->NewObject(g_featureIdClazz, featureCtorId, jMwmName.get(),
info ? static_cast<jlong>(info->GetVersion()) : 0,
static_cast<jint>(fid.m_index));
}
jobjectArray ToFeatureIdArray(JNIEnv * env, vector<FeatureID> const & ids)
{
if (ids.empty())
return nullptr;
return jni::ToJavaArray(env, g_featureIdClazz, ids,
[](JNIEnv * env, FeatureID const & fid) {
return CreateFeatureId(env, fid);
});
}
} // namespace usermark_helper

View file

@ -39,4 +39,7 @@ jintArray ToReachableByTaxiProvidersArray(JNIEnv * env, vector<taxi::Provider::T
jobject CreateLocalAdInfo(JNIEnv * env, place_page::Info const & info);
jobject CreateRoutePointInfo(JNIEnv * env, place_page::Info const & info);
jobject CreateFeatureId(JNIEnv * env, FeatureID const & fid);
jobjectArray ToFeatureIdArray(JNIEnv * env, vector<FeatureID> const & ids);
} // namespace usermark_helper

View file

@ -588,7 +588,7 @@ public class MwmActivity extends BaseMwmFragmentActivity
SearchEngine.searchInteractive(mSearchController.getQuery(), System.nanoTime(),
false /* isMapAndTable */,
mFilterController != null ? mFilterController.getFilter() : null,
null /* bookingParams */);
mFilterController != null ? mFilterController.getBookingFilterParams() : null);
SearchEngine.showAllResults(mSearchController.getQuery());
}

View file

@ -0,0 +1,17 @@
package com.mapswithme.maps.search;
import android.support.annotation.Nullable;
import com.mapswithme.maps.bookmarks.data.FeatureId;
/**
* Native booking filter returns available hotels via this interface.
*/
@SuppressWarnings("unused")
public interface NativeBookingFilterListener
{
/**
* @param availableHotels Array of available hotels feature ids.
*/
void onFilterAvailableHotels(@Nullable FeatureId[] availableHotels);
}

View file

@ -4,6 +4,7 @@ import java.io.UnsupportedEncodingException;
import com.mapswithme.maps.Framework;
import com.mapswithme.maps.api.ParsedMwmRequest;
import com.mapswithme.maps.bookmarks.data.FeatureId;
import com.mapswithme.util.Language;
import com.mapswithme.util.Listeners;
import com.mapswithme.util.concurrency.UiThread;
@ -12,7 +13,8 @@ import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
public enum SearchEngine implements NativeSearchListener,
NativeMapSearchListener
NativeMapSearchListener,
NativeBookingFilterListener
{
INSTANCE;
@ -65,6 +67,12 @@ public enum SearchEngine implements NativeSearchListener,
});
}
@Override
public void onFilterAvailableHotels(FeatureId[] availableHotels)
{
//TODO: implement
}
private final Listeners<NativeSearchListener> mListeners = new Listeners<>();
private final Listeners<NativeMapSearchListener> mMapListeners = new Listeners<>();
@ -99,11 +107,14 @@ public enum SearchEngine implements NativeSearchListener,
* @param timestamp Search results are filtered according to it after multiple requests.
* @return whether search was actually started.
*/
public static boolean search(String query, long timestamp, boolean hasLocation, double lat, double lon, @Nullable HotelsFilter hotelsFilter)
public static boolean search(String query, long timestamp, boolean hasLocation,
double lat, double lon, @Nullable HotelsFilter hotelsFilter,
@Nullable BookingFilterParams bookingParams)
{
try
{
return nativeRunSearch(query.getBytes("utf-8"), Language.getKeyboardLocale(), timestamp, hasLocation, lat, lon, hotelsFilter);
return nativeRunSearch(query.getBytes("utf-8"), Language.getKeyboardLocale(),
timestamp, hasLocation, lat, lon, hotelsFilter, bookingParams);
} catch (UnsupportedEncodingException ignored) { }
return false;
@ -115,7 +126,8 @@ public enum SearchEngine implements NativeSearchListener,
{
try
{
nativeRunInteractiveSearch(query.getBytes("utf-8"), locale, timestamp, isMapAndTable, hotelsFilter, bookingParams);
nativeRunInteractiveSearch(query.getBytes("utf-8"), locale, timestamp, isMapAndTable,
hotelsFilter, bookingParams);
} catch (UnsupportedEncodingException ignored) { }
}
@ -179,7 +191,8 @@ public enum SearchEngine implements NativeSearchListener,
* @param bytes utf-8 formatted bytes of query.
*/
private static native boolean nativeRunSearch(byte[] bytes, String language, long timestamp, boolean hasLocation,
double lat, double lon, @Nullable HotelsFilter hotelsFilter);
double lat, double lon, @Nullable HotelsFilter hotelsFilter,
@Nullable BookingFilterParams bookingParams);
/**
* @param bytes utf-8 formatted query bytes
@ -187,7 +200,7 @@ public enum SearchEngine implements NativeSearchListener,
*/
private static native void nativeRunInteractiveSearch(byte[] bytes, String language, long timestamp,
boolean isMapAndTable, @Nullable HotelsFilter hotelsFilter,
BookingFilterParams bookingParams);
@Nullable BookingFilterParams bookingParams);
/**
* @param bytes utf-8 formatted query bytes

View file

@ -37,6 +37,9 @@ public class SearchFilterController
@Nullable
private HotelsFilter mFilter;
@Nullable
private BookingFilterParams mBookingFilterParams;
private final float mElevation;
@NonNull
@ -182,6 +185,17 @@ public class SearchFilterController
}
}
@Nullable
public BookingFilterParams getBookingFilterParams()
{
return mBookingFilterParams;
}
public void setBookingFilterParams(@Nullable BookingFilterParams params)
{
mBookingFilterParams = params;
}
public boolean onBackPressed()
{
return mFilterView.close();

View file

@ -579,13 +579,18 @@ public class SearchFragment extends BaseMwmFragment
mLastQueryTimestamp = System.nanoTime();
HotelsFilter hotelsFilter = null;
BookingFilterParams bookingFilterParams = null;
if (mFilterController != null)
{
hotelsFilter = mFilterController.getFilter();
bookingFilterParams = mFilterController.getBookingFilterParams();
}
SearchEngine.searchInteractive(
query, !TextUtils.isEmpty(mInitialLocale)
? mInitialLocale : com.mapswithme.util.Language.getKeyboardLocale(),
mLastQueryTimestamp, false /* isMapAndTable */, hotelsFilter, null /* bookingParams */);
mLastQueryTimestamp, false /* isMapAndTable */,
hotelsFilter, bookingFilterParams);
SearchEngine.showAllResults(query);
Utils.navigateToParent(getActivity());
@ -622,19 +627,24 @@ public class SearchFragment extends BaseMwmFragment
private void runSearch()
{
HotelsFilter hotelsFilter = null;
BookingFilterParams bookingFilterParams = null;
if (mFilterController != null)
{
hotelsFilter = mFilterController.getFilter();
bookingFilterParams = mFilterController.getBookingFilterParams();
}
mLastQueryTimestamp = System.nanoTime();
if (isInteractiveSearch())
{
SearchEngine.searchInteractive(
getQuery(), mLastQueryTimestamp, true /* isMapAndTable */, hotelsFilter, null /* bookingParams */);
SearchEngine.searchInteractive(getQuery(), mLastQueryTimestamp, true /* isMapAndTable */,
hotelsFilter, bookingFilterParams);
}
else
{
if (!SearchEngine.search(getQuery(), mLastQueryTimestamp, mLastPosition.valid,
mLastPosition.lat, mLastPosition.lon, hotelsFilter))
mLastPosition.lat, mLastPosition.lon,
hotelsFilter, bookingFilterParams))
{
return;
}

View file

@ -1,5 +1,7 @@
package com.mapswithme.maps.search;
import com.mapswithme.maps.bookmarks.data.FeatureId;
import static com.mapswithme.maps.search.SearchResultTypes.TYPE_LOCAL_ADS_CUSTOMER;
import static com.mapswithme.maps.search.SearchResultTypes.TYPE_RESULT;
import static com.mapswithme.maps.search.SearchResultTypes.TYPE_SUGGEST;
@ -17,6 +19,7 @@ public class SearchResult implements SearchData
public static class Description
{
public final FeatureId featureId;
public final String featureType;
public final String region;
public final String distance;
@ -26,9 +29,10 @@ public class SearchResult implements SearchData
public final int stars;
public final int openNow;
public Description(String featureType, String region, String distance,
public Description(FeatureId featureId, String featureType, String region, String distance,
String cuisine, String rating, String pricing, int stars, int openNow)
{
this.featureId = featureId;
this.featureType = featureType;
this.region = region;
this.distance = distance;