[android] Core opening hours integration.

This commit is contained in:
Dmitry Yunitsky 2016-01-05 15:43:44 +03:00 committed by Sergey Yershov
parent 6ce5de362c
commit dfefd19efe
6 changed files with 474 additions and 5 deletions

View file

@ -25,8 +25,8 @@ define add_prebuild_static_lib
include $(PREBUILT_STATIC_LIBRARY)
endef
prebuild_static_libs := osrm protobuf tomcrypt jansson minizip fribidi freetype expat succinct opening_hours pugixml oauthcpp \
base coding geometry editor platform indexer storage search routing drape drape_frontend map stats_client
prebuild_static_libs := map drape_frontend routing search storage indexer drape platform editor geometry coding base opening_hours
prebuild_static_libs += pugixml oauthcpp expat freetype fribidi minizip jansson tomcrypt protobuf osrm stats_client succinct
$(foreach item,$(prebuild_static_libs),$(eval $(call add_prebuild_static_lib,$(item))))
@ -41,8 +41,7 @@ LOCAL_CPP_FEATURES += exceptions rtti
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../../
LOCAL_MODULE := mapswithme
LOCAL_STATIC_LIBRARIES := map drape_frontend routing search storage indexer drape platform editor geometry coding base \
expat freetype fribidi minizip jansson tomcrypt protobuf osrm stats_client succinct opening_hours pugixml oauthcpp
LOCAL_STATIC_LIBRARIES := $(prebuild_static_libs)
LOCAL_CFLAGS := -ffunction-sections -fdata-sections -Wno-extern-c-compat
@ -100,10 +99,11 @@ LOCAL_SRC_FILES := \
com/mapswithme/platform/MethodRef.cpp \
com/mapswithme/platform/PThreadImpl.cpp \
com/mapswithme/util/StringUtils.cpp \
com/mapswithme/util/Config.cpp \
com/mapswithme/util/Config.cpp \
com/mapswithme/opengl/android_gl_utils.cpp \
com/mapswithme/opengl/androidoglcontext.cpp \
com/mapswithme/opengl/androidoglcontextfactory.cpp \
com/mapswithme/maps/editor/OpeningHours.cpp \
LOCAL_LDLIBS := -llog -landroid -lEGL -lGLESv2 -latomic -lz

View file

@ -0,0 +1,316 @@
#include <jni.h>
#include "com/mapswithme/core/jni_helper.hpp"
#include "editor/opening_hours_ui.hpp"
#include "editor/ui2oh.hpp"
#include "base/logging.hpp"
#include "std/algorithm.hpp"
#include "std/set.hpp"
#include "std/vector.hpp"
#include "3party/opening_hours/opening_hours.hpp"
namespace
{
using namespace editor;
using namespace editor::ui;
using namespace osmoh;
using THours = std::chrono::hours;
using TMinutes = std::chrono::minutes;
// ID-s for HoursMinutes class
jclass g_clazzHoursMinutes;
jmethodID g_ctorHoursMinutes;
jfieldID g_fidHours;
jfieldID g_fidMinutes;
// ID-s for Timespan class
jclass g_clazzTimespan;
jmethodID g_ctorTimespan;
jfieldID g_fidStart;
jfieldID g_fidEnd;
// ID-s for Timetable class
jclass g_clazzTimetable;
jmethodID g_ctorTimetable;
jfieldID g_fidWorkingTimespan;
jfieldID g_fidClosedTimespans;
jfieldID g_fidIsFullday;
jfieldID g_fidWeekdays;
jobject JavaHoursMinutes(JNIEnv * env, jlong hours, jlong minutes)
{
jobject const hoursMinutes = env->NewObject(g_clazzHoursMinutes, g_ctorHoursMinutes, hours, minutes);
ASSERT(hoursMinutes, (jni::DescribeException()));
return hoursMinutes;
}
jobject JavaTimespan(JNIEnv * env, jobject start, jobject end)
{
jobject const span = env->NewObject(g_clazzTimespan, g_ctorTimespan, start, end);
ASSERT(span, (jni::DescribeException()));
return span;
}
jobject JavaTimespan(JNIEnv * env, osmoh::Timespan const & timespan)
{
auto const start = timespan.GetStart();
auto const end = timespan.GetEnd();
return JavaTimespan(env,
JavaHoursMinutes(env, start.GetHoursCount(), start.GetMinutesCount()),
JavaHoursMinutes(env, end.GetHoursCount(), end.GetMinutesCount()));
}
jobjectArray JavaTimespans(JNIEnv * env, vector<Timespan> const & spans)
{
int const size = spans.size();
jobjectArray const result = env->NewObjectArray(size, g_clazzTimespan, 0);
for (int i = 0; i < size; i++)
{
jobject const jSpan = JavaTimespan(env, spans[i]);
env->SetObjectArrayElement(result, i, jSpan);
env->DeleteLocalRef(jSpan);
}
return result;
}
jobject JavaTimetable(JNIEnv * env, jobject workingHours, jobject closedHours, bool isFullday, jintArray weekdays)
{
jobject const tt = env->NewObject(g_clazzTimetable, g_ctorTimetable, workingHours, closedHours, isFullday, weekdays);
ASSERT(tt, (jni::DescribeException()));
return tt;
}
jobject JavaTimetable(JNIEnv * env, TimeTable const & tt)
{
auto const excludeSpans = tt.GetExcludeTime();
set<Weekday> weekdays = tt.GetOpeningDays();
vector<int> weekdaysVector;
weekdaysVector.reserve(weekdays.size());
transform(weekdays.begin(), weekdays.end(), back_inserter(weekdaysVector), [](Weekday weekday)
{
return static_cast<int>(weekday);
});
jintArray jWeekdays = env->NewIntArray(weekdays.size());
env->SetIntArrayRegion(jWeekdays, 0, weekdaysVector.size(), &weekdaysVector[0]);
return JavaTimetable(env,
JavaTimespan(env, tt.GetOpeningTime()),
JavaTimespans(env, tt.GetExcludeTime()),
tt.IsTwentyFourHours(),
jWeekdays);
}
jobjectArray JavaTimetables(JNIEnv * env, TimeTableSet & tts)
{
int const size = tts.Size();
jobjectArray const result = env->NewObjectArray(size, g_clazzTimetable, 0);
for (int i = 0; i < size; i++)
{
jobject const jTable = JavaTimetable(env, tts.Get(i));
env->SetObjectArrayElement(result, i, jTable);
env->DeleteLocalRef(jTable);
}
return result;
}
HourMinutes NativeHoursMinutes(JNIEnv * env, jobject jHourMinutes)
{
jlong const hours = env->GetLongField(jHourMinutes, g_fidHours);
jlong const minutes = env->GetLongField(jHourMinutes, g_fidMinutes);
return HourMinutes(THours(hours) + TMinutes(minutes));
}
Timespan NativeTimespan(JNIEnv * env, jobject jTimespan)
{
Timespan span;
span.SetStart(NativeHoursMinutes(env, env->GetObjectField(jTimespan, g_fidStart)));
span.SetEnd(NativeHoursMinutes(env, env->GetObjectField(jTimespan, g_fidEnd)));
return span;
}
TimeTable NativeTimetable(JNIEnv * env, jobject jTimetable)
{
TimeTable tt = TimeTable::GetPredefinedTimeTable();
jintArray const jWeekdays = static_cast<jintArray>(env->GetObjectField(jTimetable, g_fidWeekdays));
int * weekdaysArr = static_cast<int*>(env->GetIntArrayElements(jWeekdays, nullptr));
jint size = env->GetArrayLength(jWeekdays);
std::set<Weekday> weekdays;
for (int i = 0; i < size; i++)
weekdays.insert(ToWeekday(weekdaysArr[i]));
tt.SetOpeningDays(weekdays);
env->ReleaseIntArrayElements(jWeekdays, weekdaysArr, 0);
tt.SetTwentyFourHours(env->GetBooleanField(jTimetable, g_fidIsFullday));
tt.SetOpeningTime(NativeTimespan(env, env->GetObjectField(jTimetable, g_fidWorkingTimespan)));
jobjectArray jClosedSpans = static_cast<jobjectArray>(env->GetObjectField(jTimetable, g_fidClosedTimespans));
size = env->GetArrayLength(jClosedSpans);
for (int i = 0; i < size; i++)
{
jobject const jSpan = env->GetObjectArrayElement(jClosedSpans, i);
if (jSpan)
{
tt.AddExcludeTime(NativeTimespan(env, jSpan));
env->DeleteLocalRef(jSpan);
}
}
return tt;
}
TimeTableSet NativeTimetableSet(JNIEnv * env, jobjectArray jTimetables)
{
TimeTableSet tts;
int const size = env->GetArrayLength(jTimetables);
jobject const timetable = env->GetObjectArrayElement(jTimetables, 0);
tts.Replace(NativeTimetable(env, timetable), 0);
for (int i = 1; i < size; i++)
{
jobject const timetable = env->GetObjectArrayElement(jTimetables, i);
tts.Append(NativeTimetable(env, timetable));
env->DeleteLocalRef(timetable);
}
return tts;
}
} // namespace
extern "C"
{
JNIEXPORT void JNICALL
Java_com_mapswithme_maps_editor_OpeningHours_nativeInit(JNIEnv * env, jclass clazz)
{
g_clazzHoursMinutes = jni::GetGlobalClassRef(env, "com/mapswithme/maps/editor/data/HoursMinutes");
// Java signature : HoursMinutes(@IntRange(from = 0, to = 24) long hours, @IntRange(from = 0, to = 60) long minutes)
g_ctorHoursMinutes = env->GetMethodID(g_clazzHoursMinutes, "<init>", "(JJ)V");
ASSERT(g_ctorHoursMinutes, (jni::DescribeException()));
g_fidHours = env->GetFieldID(g_clazzHoursMinutes, "hours", "J");
ASSERT(g_fidHours, (jni::DescribeException()));
g_fidMinutes = env->GetFieldID(g_clazzHoursMinutes, "minutes", "J");
ASSERT(g_fidMinutes, (jni::DescribeException()));
g_clazzTimespan = jni::GetGlobalClassRef(env, "com/mapswithme/maps/editor/data/Timespan");
// Java signature : Timespan(HoursMinutes start, HoursMinutes end)
g_ctorTimespan =
env->GetMethodID(g_clazzTimespan, "<init>","(Lcom/mapswithme/maps/editor/data/HoursMinutes;Lcom/mapswithme/maps/editor/data/HoursMinutes;)V");
ASSERT(g_ctorTimespan, (jni::DescribeException()));
g_fidStart = env->GetFieldID(g_clazzTimespan, "start", "Lcom/mapswithme/maps/editor/data/HoursMinutes;");
ASSERT(g_fidStart, (jni::DescribeException()));
g_fidEnd = env->GetFieldID(g_clazzTimespan, "end", "Lcom/mapswithme/maps/editor/data/HoursMinutes;");
ASSERT(g_fidEnd, (jni::DescribeException()));
g_clazzTimetable = jni::GetGlobalClassRef(env, "com/mapswithme/maps/editor/data/Timetable");
// Java signature : Timetable(Timespan workingTime, Timespan[] closedHours, boolean isFullday, int weekdays[])
g_ctorTimetable =
env->GetMethodID(g_clazzTimetable, "<init>","(Lcom/mapswithme/maps/editor/data/Timespan;[Lcom/mapswithme/maps/editor/data/Timespan;Z[I)V");
ASSERT(g_ctorTimetable, (jni::DescribeException()));
g_fidWorkingTimespan = env->GetFieldID(g_clazzTimetable, "workingTimespan", "Lcom/mapswithme/maps/editor/data/Timespan;");
ASSERT(g_fidWorkingTimespan, (jni::DescribeException()));
g_fidClosedTimespans = env->GetFieldID(g_clazzTimetable, "closedTimespans", "[Lcom/mapswithme/maps/editor/data/Timespan;");
ASSERT(g_fidClosedTimespans, (jni::DescribeException()));
g_fidIsFullday = env->GetFieldID(g_clazzTimetable, "isFullday", "Z");
ASSERT(g_fidIsFullday, (jni::DescribeException()));
g_fidWeekdays = env->GetFieldID(g_clazzTimetable, "weekdays", "[I");
ASSERT(g_fidWeekdays, (jni::DescribeException()));
}
JNIEXPORT jobjectArray JNICALL
Java_com_mapswithme_maps_editor_OpeningHours_nativeGetDefaultTimetables(JNIEnv * env, jclass clazz)
{
TimeTableSet tts;
return JavaTimetables(env, tts);
}
JNIEXPORT jobject JNICALL
Java_com_mapswithme_maps_editor_OpeningHours_nativeGetComplementTimetable(JNIEnv * env, jclass clazz, jobjectArray timetables)
{
TimeTableSet const tts = NativeTimetableSet(env, timetables);
return JavaTimetable(env, tts.GetComplementTimeTable());
}
JNIEXPORT jobject JNICALL
Java_com_mapswithme_maps_editor_OpeningHours_nativeRemoveWorkingDay(JNIEnv * env, jclass clazz,
jobjectArray timetables, jint ttIndex, jint dayIndex)
{
TimeTableSet tts = NativeTimetableSet(env, timetables);
auto tt = tts.Get(ttIndex);
tt.RemoveWorkingDay(ToWeekday(dayIndex));
tt.Commit();
return JavaTimetables(env, tts);
}
JNIEXPORT jobject JNICALL
Java_com_mapswithme_maps_editor_OpeningHours_nativeAddWorkingDay(JNIEnv * env, jclass clazz,
jobjectArray timetables, jint ttIndex, jint dayIndex)
{
TimeTableSet tts = NativeTimetableSet(env, timetables);
auto tt = tts.Get(ttIndex);
tt.AddWorkingDay(ToWeekday(dayIndex));
tt.Commit();
return JavaTimetables(env, tts);
}
JNIEXPORT jobject JNICALL
Java_com_mapswithme_maps_editor_OpeningHours_nativeSetIsFullday(JNIEnv * env, jclass clazz,
jobject jTimetable, jboolean jIsFullday)
{
TimeTable tt = NativeTimetable(env, jTimetable);
if (jIsFullday)
tt.SetTwentyFourHours(true);
else
{
tt.SetTwentyFourHours(false);
tt.SetOpeningTime(tt.GetPredefinedOpeningTime());
}
return JavaTimetable(env, tt);
}
JNIEXPORT jobject JNICALL
Java_com_mapswithme_maps_editor_OpeningHours_nativeSetOpeningTime(JNIEnv * env, jclass clazz,
jobject jTimetable, jobject jOpeningTime)
{
TimeTable tt = NativeTimetable(env, jTimetable);
tt.SetOpeningTime(NativeTimespan(env, jOpeningTime));
return JavaTimetable(env, tt);
}
JNIEXPORT jobject JNICALL
Java_com_mapswithme_maps_editor_OpeningHours_nativeAddClosedSpan(JNIEnv * env, jclass clazz,
jobject jTimetable, jobject jClosedSpan)
{
TimeTable tt = NativeTimetable(env, jTimetable);
tt.AddExcludeTime(NativeTimespan(env, jClosedSpan));
return JavaTimetable(env, tt);
}
JNIEXPORT jobject JNICALL
Java_com_mapswithme_maps_editor_OpeningHours_nativeRemoveClosedSpan(JNIEnv * env, jclass clazz,
jobject jTimetable, jint jClosedSpanIndex)
{
TimeTable tt = NativeTimetable(env, jTimetable);
tt.RemoveExcludeTime(static_cast<size_t>(jClosedSpanIndex));
return JavaTimetable(env, tt);
}
JNIEXPORT jobjectArray JNICALL
Java_com_mapswithme_maps_editor_OpeningHours_nativeTimetablesFromString(JNIEnv * env, jclass clazz, jstring jSource)
{
TimeTableSet tts;
if (MakeTimeTableSet(OpeningHours(jni::ToNativeString(env, jSource)), tts))
return JavaTimetables(env, tts);
return nullptr;
}
JNIEXPORT jstring JNICALL
Java_com_mapswithme_maps_editor_OpeningHours_nativeTimetablesToString(JNIEnv * env, jclass clazz, jobjectArray jTts)
{
TimeTableSet tts = NativeTimetableSet(env, jTts);
stringstream sstr;
sstr << MakeOpeningHours(tts).GetRule();
return jni::ToJavaString(env, sstr.str());
}
}

View file

@ -0,0 +1,42 @@
package com.mapswithme.maps.editor;
import android.support.annotation.IntRange;
import com.mapswithme.maps.editor.data.Timespan;
import com.mapswithme.maps.editor.data.Timetable;
public final class OpeningHours
{
private OpeningHours() {}
static
{
nativeInit();
}
private static native void nativeInit();
public static native Timetable[] nativeGetDefaultTimetables();
public static native Timetable nativeGetComplementTimetable(Timetable[] timetableSet);
public static native Timetable[] nativeAddTimetable(Timetable[] timetableSet);
public static native Timetable[] nativeRemoveTimetable(Timetable[] timetableSet, int timetableIndex);
public static native Timetable nativeSetIsFullday(Timetable timetable, boolean isFullday);
public static native Timetable[] nativeAddWorkingDay(Timetable[] timetables, int timetableIndex, @IntRange(from = 1, to = 7) int day);
public static native Timetable[] nativeRemoveWorkingDay(Timetable[] timetables, int timetableIndex, @IntRange(from = 1, to = 7) int day);
public static native Timetable nativeSetOpeningTime(Timetable timetable, Timespan openingTime);
public static native Timetable nativeAddClosedSpan(Timetable timetable, Timespan closedSpan);
public static native Timetable nativeRemoveClosedSpan(Timetable timetable, int spanIndex);
public static native Timetable[] nativeTimetablesFromString(String source);
public static native String nativeTimetablesToString(Timetable timetables[]);
}

View file

@ -0,0 +1,57 @@
package com.mapswithme.maps.editor.data;
import android.os.Parcel;
import android.os.Parcelable;
import android.support.annotation.IntRange;
public class HoursMinutes implements Parcelable
{
public final long hours;
public final long minutes;
public HoursMinutes(@IntRange(from = 0, to = 23) long hours, @IntRange(from = 0, to = 59) long minutes)
{
this.hours = hours;
this.minutes = minutes;
}
protected HoursMinutes(Parcel in)
{
hours = in.readLong();
minutes = in.readLong();
}
@Override
public String toString()
{
return hours + "." + minutes;
}
@Override
public int describeContents()
{
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags)
{
dest.writeLong(hours);
dest.writeLong(minutes);
}
public static final Creator<HoursMinutes> CREATOR = new Creator<HoursMinutes>()
{
@Override
public HoursMinutes createFromParcel(Parcel in)
{
return new HoursMinutes(in);
}
@Override
public HoursMinutes[] newArray(int size)
{
return new HoursMinutes[size];
}
};
}

View file

@ -0,0 +1,19 @@
package com.mapswithme.maps.editor.data;
public class Timespan
{
public final HoursMinutes start;
public final HoursMinutes end;
public Timespan(HoursMinutes start, HoursMinutes end)
{
this.start = start;
this.end = end;
}
@Override
public String toString()
{
return "From : " + start + " to : " + end;
}
}

View file

@ -0,0 +1,35 @@
package com.mapswithme.maps.editor.data;
import android.support.annotation.NonNull;
public class Timetable
{
public final Timespan workingTimespan;
public final Timespan[] closedTimespans;
public final boolean isFullday;
public final int[] weekdays;
public Timetable(@NonNull Timespan workingTime, @NonNull Timespan[] closedHours, boolean isFullday, @NonNull int[] weekdays)
{
this.workingTimespan = workingTime;
this.closedTimespans = closedHours;
this.isFullday = isFullday;
this.weekdays = weekdays;
}
@Override
public String toString()
{
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("Working timespan : ").append(workingTimespan).append("\n")
.append("Closed timespans : ");
for (Timespan timespan : closedTimespans)
stringBuilder.append(timespan).append(" ");
stringBuilder.append("\n");
stringBuilder.append("Fullday : ").append(isFullday).append("\n")
.append("Weekdays : ");
for (int i : weekdays)
stringBuilder.append(i);
return stringBuilder.toString();
}
}