[booking][jni] jni layer for booking online filter

This commit is contained in:
Arsentiy Milchakov 2017-11-16 16:37:09 +03:00 committed by Roman Kuznetsov
parent de99faf3dc
commit 282f46201c
9 changed files with 204 additions and 17 deletions

View file

@ -13,6 +13,7 @@
#include "com/mapswithme/core/jni_helper.hpp"
#include "com/mapswithme/platform/Platform.hpp"
#include <chrono>
#include <cstdint>
#include <memory>
#include <vector>
@ -242,6 +243,68 @@ private:
bool m_initialized = false;
} g_hotelsFilterBuilder;
class BookingAvailabilityParamsBuilder
{
public:
void Init(JNIEnv * env)
{
if (m_initialized)
return;
m_bookingFilterParamsClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/search/BookingFilterParams");
m_roomClass = jni::GetGlobalClassRef(env, "com/mapswithme/maps/search/BookingFilterParams$Room");
m_checkinMillisecId = env->GetFieldID(m_bookingFilterParamsClass, "mCheckinMillisec", "J");
m_checkoutMillisecId = env->GetFieldID(m_bookingFilterParamsClass, "mCheckoutMillisec", "J");
m_roomsId = env->GetFieldID(m_bookingFilterParamsClass, "mRooms",
"[Lcom/mapswithme/maps/search/BookingFilterParams$Room;");
m_roomAdultsCountId = env->GetFieldID(m_roomClass, "mAdultsCount", "I");
m_roomAgeOfChildId = env->GetFieldID(m_roomClass, "mAgeOfChild", "I");
m_initialized = true;
}
booking::AvailabilityParams Build(JNIEnv * env, jobject bookingFilterParams)
{
booking::AvailabilityParams result;
if (!m_initialized || bookingFilterParams == nullptr)
return result;
jlong const jcheckin = env->GetLongField(bookingFilterParams, m_checkinMillisecId) / 1000;
result.m_checkin = booking::AvailabilityParams::Clock::from_time_t(jcheckin);
jlong const jcheckout = env->GetLongField(bookingFilterParams, m_checkoutMillisecId) / 1000;
result.m_checkout = booking::AvailabilityParams::Clock::from_time_t(jcheckout);
jobjectArray const jrooms =
static_cast<jobjectArray>(env->GetObjectField(bookingFilterParams, m_roomsId));
auto const length = static_cast<size_t>(env->GetArrayLength(jrooms));
result.m_rooms.resize(length);
for (size_t i = 0; i < length; ++i)
{
jobject jroom = env->GetObjectArrayElement(jrooms, i);
booking::AvailabilityParams::Room room;
room.SetAdultsCount(static_cast<uint8_t>(env->GetIntField(jroom, m_roomAdultsCountId)));
room.SetAgeOfChild(static_cast<int8_t>(env->GetIntField(jroom, m_roomAgeOfChildId)));
result.m_rooms[i] = std::move(room);
}
return result;
}
private:
jclass m_bookingFilterParamsClass = nullptr;
jclass m_roomClass = nullptr;
jfieldID m_checkinMillisecId = nullptr;
jfieldID m_checkoutMillisecId = nullptr;
jfieldID m_roomsId = nullptr;
jfieldID m_roomAdultsCountId = nullptr;
jfieldID m_roomAgeOfChildId = nullptr;
bool m_initialized = false;
} g_bookingAvailabilityParamsBuilder;
// TODO yunitsky
// Do not cache search results here, after new search will be implemented.
// Currently we cannot serialize FeatureID of search result properly.
@ -422,6 +485,7 @@ extern "C"
g_mapResultCtor = jni::GetConstructorID(env, g_mapResultClass, "(Ljava/lang/String;Ljava/lang/String;)V");
g_hotelsFilterBuilder.Init(env);
g_bookingAvailabilityParamsBuilder.Init(env);
}
JNIEXPORT jboolean JNICALL Java_com_mapswithme_maps_search_SearchEngine_nativeRunSearch(
@ -442,12 +506,14 @@ extern "C"
JNIEXPORT void JNICALL Java_com_mapswithme_maps_search_SearchEngine_nativeRunInteractiveSearch(
JNIEnv * env, jclass clazz, jbyteArray bytes, jstring lang, jlong timestamp,
jboolean isMapAndTable, jobject hotelsFilter)
jboolean isMapAndTable, jobject hotelsFilter, jobject bookingFilterParams)
{
search::ViewportSearchParams vparams;
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);
// TODO (@alexzatsepin): set up vparams.m_onCompleted here and use
// HotelsClassifier for hotel queries detection.

View file

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

View file

@ -288,7 +288,8 @@ class SearchWheel implements View.OnClickListener
private void startSearch(SearchOption searchOption)
{
mCurrentOption = searchOption;
SearchEngine.searchInteractive(searchOption.mSearchQuery, System.nanoTime(), false /* isMapAndTable */, null /* hotelsFilter */);
SearchEngine.searchInteractive(searchOption.mSearchQuery, System.nanoTime(), false /* isMapAndTable */,
null /* hotelsFilter */, null /* bookingParams */);
refreshSearchButtonImage();
toggleSearchLayout();

View file

@ -0,0 +1,55 @@
package com.mapswithme.maps.search;
import android.support.annotation.NonNull;
class BookingFilterParams
{
static class Room
{
// This value is corresponds to AvailabilityParams::Room::kNoChildren in core.
static final int NO_CHILDREN = -1;
private int mAdultsCount;
private int mAgeOfChild;
Room(int adultsCount)
{
mAdultsCount = adultsCount;
mAgeOfChild = NO_CHILDREN;
}
Room(int adultsCount, int ageOfChild)
{
mAdultsCount = adultsCount;
mAgeOfChild = ageOfChild;
}
}
private long mCheckinMillisec;
private long mCheckoutMillisec;
@NonNull
private Room[] mRooms;
BookingFilterParams(long checkinMillisec, long checkoutMillisec, @NonNull Room[] rooms)
{
mCheckinMillisec = checkinMillisec;
mCheckoutMillisec = checkoutMillisec;
mRooms = rooms;
}
public long getCheckinMillisec()
{
return mCheckinMillisec;
}
public long getCheckoutMillisec()
{
return mCheckoutMillisec;
}
@NonNull
public Room[] getRooms()
{
return mRooms;
}
}

View file

@ -110,18 +110,19 @@ public enum SearchEngine implements NativeSearchListener,
}
public static void searchInteractive(@NonNull String query, @NonNull String locale, long timestamp,
boolean isMapAndTable, @Nullable HotelsFilter hotelsFilter)
boolean isMapAndTable, @Nullable HotelsFilter hotelsFilter,
@Nullable BookingFilterParams bookingParams)
{
try
{
nativeRunInteractiveSearch(query.getBytes("utf-8"), locale, timestamp, isMapAndTable, hotelsFilter);
nativeRunInteractiveSearch(query.getBytes("utf-8"), locale, timestamp, isMapAndTable, hotelsFilter, bookingParams);
} catch (UnsupportedEncodingException ignored) { }
}
public static void searchInteractive(@NonNull String query, long timestamp, boolean isMapAndTable,
@Nullable HotelsFilter hotelsFilter)
@Nullable HotelsFilter hotelsFilter, @Nullable BookingFilterParams bookingParams)
{
searchInteractive(query, Language.getKeyboardLocale(), timestamp, isMapAndTable, hotelsFilter);
searchInteractive(query, Language.getKeyboardLocale(), timestamp, isMapAndTable, hotelsFilter, bookingParams);
}
public static void searchMaps(String query, long timestamp)
@ -177,12 +178,16 @@ 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);
private static native boolean nativeRunSearch(byte[] bytes, String language, long timestamp, boolean hasLocation,
double lat, double lon, @Nullable HotelsFilter hotelsFilter);
/**
* @param bytes utf-8 formatted query bytes
* @param bookingParams
*/
private static native void nativeRunInteractiveSearch(byte[] bytes, String language, long timestamp, boolean isMapAndTable, @Nullable HotelsFilter hotelsFilter);
private static native void nativeRunInteractiveSearch(byte[] bytes, String language, long timestamp,
boolean isMapAndTable, @Nullable HotelsFilter hotelsFilter,
BookingFilterParams bookingParams);
/**
* @param bytes utf-8 formatted query bytes

View file

@ -585,7 +585,7 @@ public class SearchFragment extends BaseMwmFragment
SearchEngine.searchInteractive(
query, !TextUtils.isEmpty(mInitialLocale)
? mInitialLocale : com.mapswithme.util.Language.getKeyboardLocale(),
mLastQueryTimestamp, false /* isMapAndTable */, hotelsFilter);
mLastQueryTimestamp, false /* isMapAndTable */, hotelsFilter, null /* bookingParams */);
SearchEngine.showAllResults(query);
Utils.navigateToParent(getActivity());
@ -629,7 +629,7 @@ public class SearchFragment extends BaseMwmFragment
if (isInteractiveSearch())
{
SearchEngine.searchInteractive(
getQuery(), mLastQueryTimestamp, true /* isMapAndTable */, hotelsFilter);
getQuery(), mLastQueryTimestamp, true /* isMapAndTable */, hotelsFilter, null /* bookingParams */);
}
else
{

View file

@ -3,6 +3,8 @@
#include "base/string_utils.hpp"
#include <sstream>
using namespace base;
namespace
@ -15,6 +17,43 @@ std::string FormatTime(booking::AvailabilityParams::Time p)
namespace booking
{
AvailabilityParams::Room::Room(uint8_t adultsCount, int8_t ageOfChild)
: m_adultsCount(adultsCount), m_ageOfChild(ageOfChild)
{
}
void AvailabilityParams::Room::SetAdultsCount(uint8_t adultsCount)
{
m_adultsCount = adultsCount;
}
void AvailabilityParams::Room::SetAgeOfChild(int8_t ageOfChild)
{
m_ageOfChild = ageOfChild;
}
std::string AvailabilityParams::Room::ToString() const
{
static std::string const kAdult = "A";
std::vector<std::string> adults(m_adultsCount, kAdult);
std::string child = m_ageOfChild == kNoChildren ? "" : "," + std::to_string(m_ageOfChild);
std::ostringstream os;
os << strings::JoinStrings(adults, ',') << child;
return os.str();
}
bool AvailabilityParams::Room::operator!=(AvailabilityParams::Room const & rhs) const
{
return m_adultsCount != rhs.m_adultsCount || m_ageOfChild != rhs.m_ageOfChild;
}
bool AvailabilityParams::Room::operator==(AvailabilityParams::Room const & rhs) const
{
return !this->operator!=(rhs);
}
url::Params AvailabilityParams::Get() const
{
url::Params result;
@ -24,7 +63,7 @@ url::Params AvailabilityParams::Get() const
result.push_back({"checkout", FormatTime(m_checkout)});
for (size_t i = 0; i < m_rooms.size(); ++i)
result.push_back({"room" + to_string(i + 1), m_rooms[i]});
result.push_back({"room" + to_string(i + 1), m_rooms[i].ToString()});
if (m_minReviewScore != 0.0)
result.push_back({"min_review_score", to_string(m_minReviewScore)});
@ -43,7 +82,7 @@ bool AvailabilityParams::IsEmpty() const
bool AvailabilityParams::operator!=(AvailabilityParams const & rhs) const
{
return m_checkin != rhs.m_checkin || m_checkout != rhs.m_checkout || m_rooms != rhs.m_rooms ||
m_minReviewScore != m_minReviewScore || m_stars != rhs.m_stars;
m_minReviewScore != rhs.m_minReviewScore || m_stars != rhs.m_stars;
}
bool AvailabilityParams::operator==(AvailabilityParams const & rhs) const
{

View file

@ -12,9 +12,29 @@ namespace booking
/// [m_hotelIds], [m_checkin], [m_checkout], [m_rooms] are required.
struct AvailabilityParams
{
using Time = std::chrono::system_clock::time_point;
struct Room
{
static constexpr int8_t kNoChildren = -1;
Room() = default;
Room(uint8_t adultsCount, int8_t ageOfChild);
void SetAdultsCount(uint8_t adultsCount);
void SetAgeOfChild(int8_t ageOfChild);
std::string ToString() const;
bool operator!=(Room const & rhs) const;
bool operator==(Room const & rhs) const;
private:
uint8_t m_adultsCount = 0;
// No children by default.
int8_t m_ageOfChild = kNoChildren;
};
using Clock = std::chrono::system_clock;
using Time = Clock::time_point;
using Hotels = std::vector<std::string>;
using Rooms = std::vector<std::string>;
using Rooms = std::vector<Room>;
using Stars = std::vector<std::string>;
base::url::Params Get() const;

View file

@ -45,7 +45,7 @@ UNIT_TEST(Booking_HotelAvailability)
{
AvailabilityParams params;
params.m_hotelIds = {"98251"};
params.m_rooms = {"A,A"};
params.m_rooms = {{2, AvailabilityParams::Room::kNoChildren}};
params.m_checkin = std::chrono::system_clock::now() + std::chrono::hours(24);
params.m_checkout = std::chrono::system_clock::now() + std::chrono::hours(24 * 7);
params.m_stars = {"4", "5"};
@ -141,7 +141,7 @@ UNIT_CLASS_TEST(AsyncGuiThreadBooking, GetHotelAvailability)
{
AvailabilityParams params;
params.m_hotelIds = {"0"}; // Internal hotel id for testing.
params.m_rooms = {"A,A"};
params.m_rooms = {{2, AvailabilityParams::Room::kNoChildren}};
params.m_checkin = std::chrono::system_clock::now() + std::chrono::hours(24);
params.m_checkout = std::chrono::system_clock::now() + std::chrono::hours(24 * 7);
params.m_stars = {"4"};