مكتبة Java (Java SDK)
مكتبة Java (Java SDK)
مكتبة io.navvo:navvo-java الرسمية هي عميل من جهة الخادم بلغة Java لخدمة
Navvo على الويب. وهي مكتوبة بأنواع محدّدة، وتعيد المحاولة تلقائيًا، وآمنة
للاستخدام المتزامن، ومبنية على JDK 11 الصِّرف (java.net.http.HttpClient)
مع محلّل JSON صغير مضمّن — بلا أي تبعيات خارجية (لا Jackson ولا Guava). وهي
متوافقة مع Kotlin، وتوفّر دوالّ متزامنة ونظائر غير متزامنة عبر
CompletableFuture. لا تحتوي على واجهة خرائط ولا عرض بلاطات — لعرض خريطة في
المتصفح استخدم خرائط Navvo.
يتطلّب: Java 11+ (يعمل على 11 / 17 / 21) · عنوان الأساس: https://navvo.io/api/v1
التثبيت
<dependency>
<groupId>io.navvo</groupId>
<artifactId>navvo-java</artifactId>
<version>0.1.0</version>
</dependency>
implementation 'io.navvo:navvo-java:0.1.0'
import io.navvo.NavvoClient;
import io.navvo.model.*;
المصادقة
تُرسَل كل الاستدعاءات عبر ترويسة x-api-key. مرّر المفتاح صراحةً، أو استخدم
NavvoClient.fromEnv() لقراءته من متغيّر البيئة NAVVO_API_KEY. يتم التحقق من
شكل المفتاح (nvvo_<48 hex>) مسبقًا، ولا يُسجَّل المفتاح أبدًا — إذ يُخفى إلى
nvvo_****<آخر 4> في كل مكان.
NavvoClient navvo = NavvoClient.fromEnv(); // يستخدم $NAVVO_API_KEY
NavvoClient navvo = NavvoClient.builder()
.apiKey("nvvo_your_key_here")
.build();
لا تضع المكتبة المفتاح في عنوان URL إطلاقًا — باستثناء styleUrl() التي تبني
عنوان نمط خريطة قابلًا للجلب من المتصفح حيث يجب أن
يُمرَّر المفتاح بصيغة ?api_key= (لا يمكن للمتصفحات ضبط الترويسات على طلبات
البلاطات/الأنماط).
البدء السريع
import io.navvo.NavvoClient;
import io.navvo.model.*;
import java.util.*;
public class Demo {
public static void main(String[] args) {
try (NavvoClient navvo = NavvoClient.fromEnv()) {
// ترميز جغرافي أمامي — تُحوَّل الإحداثيات النصّية إلى أرقام تلقائيًا.
List<GeocodeResult> hits = navvo.geocode(
GeocodeQuery.builder().q("مستشفى العبدلي, عمّان").limit(5).build());
GeocodeResult top = hits.get(0);
System.out.println(top.lat() + "," + top.lng() + " " + top.displayName());
// خطّط مسارًا — تمرّر LatLng(lat, lng) وتتولّى المكتبة ترتيب lon/lat على السلك.
RoutePlan plan = navvo.route(RoutePlanRequest.builder()
.addLocation(LatLng.named(31.95, 35.91, "أ"))
.addLocation(LatLng.named(31.99, 35.95, "ب"))
.costing("auto")
.build());
System.out.println("الوقت المتوقّع بالثواني: " + plan.durationSeconds());
// فكّ ترميز خط المسار (polyline6) إلى نقاط.
List<LatLng> line = plan.geometry();
System.out.println("عدد نقاط الشكل: " + line.size());
// إضافات حيّة (NavvoObject مع منفذ raw() الاحتياطي).
NavvoObject wx = navvo.weatherPoint(31.95, 35.91, "metric");
System.out.println(wx.raw());
}
}
}
الإعداد
اضبط عبر الباني (builder):
NavvoClient navvo = NavvoClient.builder()
.apiKey(System.getenv("NAVVO_API_KEY"))
.baseUrl("https://navvo.io/api/v1")
.timeout(java.time.Duration.ofSeconds(15))
.connectTimeout(java.time.Duration.ofSeconds(5))
.userAgent("acme-dispatch/2.3")
.retry(RetryConfig.builder()
.retries(3)
.baseDelay(java.time.Duration.ofMillis(500))
.maxDelay(java.time.Duration.ofSeconds(20))
.factor(2).jitter(true).respectRetryAfter(true)
.build())
.build();
استخدم navvo.withApiKey(key) لاستنساخ عميل بمفتاح مختلف (خوادم متعدّدة
المستأجرين). كائن NavvoClient غير قابل للتغيير وآمن للاستخدام المتزامن عبر
الخيوط، وهو AutoCloseable للاستخدام مع try-with-resources.
الإحداثيات — لن تنعكس أبدًا
تمرّر النقاط دائمًا كـ LatLng.of(lat, lng) (أو LatLng.named(lat, lng, name)
لنقطة طريق). تتولّى المكتبة كل اختلافات صيغة السلك: {lon, lat} لـ
route/trafficRoute، و{lat, lon} لحمولات المرور المباشرة
(simpleRoute/matrix/optimizeStops)، ومعاملات lat/lon منفصلة للترميز
العكسي، وwest,south,east,north لـ BBox، و[lng, lat] لـ GeoJSON، وصيغة WKT
POINT(lng lat) لمركز المكان (افكُكها بـ place.centerLatLng()).
LatLng amman = LatLng.of(31.9539, 35.9106);
BBox box = BBox.fromCorners(35.85, 31.92, 35.98, 32.02); // west, south, east, north
إعادة المحاولة والأخطاء
تُعاد محاولة الأعطال العابرة (5xx، 408، 429/الحصّة، انقطاعات الشبكة، وأغلفة
available:false) بتراجع أُسّي مع تشويش كامل، مع احترام Retry-After؛ أمّا أخطاء
العميل (400/401/403/404) فلا يُعاد محاولتها. كل خطأ هو نوع فرعي غير مُتحقَّق
من NavvoException:
try {
navvo.geocode(GeocodeQuery.of("مستشفى العبدلي, عمّان"));
} catch (NavvoRateLimitException e) {
log.warn("تم تجاوز الحد، أعد المحاولة بعد {}", e.retryAfter());
} catch (NavvoScopeException e) {
log.error("نطاق/حصّة: {} (ناقص {})", e.reason(), e.scope());
} catch (NavvoServiceUnavailableException e) {
log.error("محرّك الترميز الجغرافي معطّل — استخدم بديلًا");
}
يُفكّ غلاف الترميز/المسارات ({ provider, available, data }) تلقائيًا — ويصبح
جسم available:false استثناءً من نوع NavvoServiceUnavailableException — ويعيد
المعرّف المجهول للمكان Optional فارغًا (قيمة null لطيفة، وليست خطأً).
| الاستثناء | المصدر |
|---|---|
NavvoConfigException | مفتاح خاطئ/مفقود، خيار خاطئ، عنوان أساس غير HTTPS |
NavvoValidationException | 400 (وبقية 4xx غير القابلة لإعادة المحاولة) |
NavvoAuthException | 401 |
NavvoScopeException | 403 (يحمل reason()، scope()) |
NavvoNotFoundException | 404 |
NavvoRateLimitException | 429 (يحمل retryAfter()، limit()، remaining()، resetAt()) |
NavvoServiceUnavailableException | available:false، 502/503 |
NavvoServerException | بقية 5xx |
NavvoTimeoutException / NavvoNetworkException | مهلة / نقل |
يُرسَل المفتاح فقط في ترويسة x-api-key ولا يظهر في أي خطأ؛ تحمل الأخطاء
redactedKey() (nvvo_****<آخر 4>).
خريطة الدوالّ
| المجال | الدوالّ |
|---|---|
| البلاطات والإعداد | styles، styleUrl، mapConfig |
| البحث والترميز الجغرافي | search، geocode، reverseGeocode، geocodeBatch، reverseGeocodeBatch |
| الأماكن | places، placesStream، place، placeCategories، placeFacets، placeThumb، placeHours، placePopularTimes، placeAttributes، placeReviewsSummary، placePhotos، placeNearby، placesReachable |
| المسارات | route، simpleRoute، matrix، isochrone، mapMatch، optimizeStops، optimize، routingProfiles |
| حركة المرور والحوادث | trafficRoute، trafficSummary، incidents، incidentTypes، reportIncident، roadEdits، routeRisk |
| الطقس وجودة الهواء | weatherPoint، weatherForecast، weatherCities، airQualityCities |
| المركبات الكهربائية والنقل | evStations، transitStops، gbfs |
تُقابل كل دالّة نقطة النهاية الموثّقة في مرجع الـ API. تكشف
النتائج المُنمَّطة عن raw() الذي يحوي الجسم الكامل غير المُنمَّط للتوافق
المستقبلي؛ وتعيد الاستجابات الأقل بنيةً كائن NavvoObject الذي يعيد raw() فيه
الشجرة المُحلَّلة. تتطلّب optimize نطاق optimize الاختياري؛ وتتطلّب
trafficRoute نطاقَي routing وtraffic معًا. راجع
تحسين المسارات و
حركة المرور والحوادث.
الترقيم الصفحي وغير المتزامن
نقطة GET /places مُرقَّمة صفحيًا؛ وتمرّ placesStream(query) على كل الصفحات
بكسل:
navvo.placesStream(PlaceListQuery.builder().category("restaurants").limit(100).build())
.forEach(p -> System.out.println(p.nameEn()));
تملك الدوالّ الأساسية نظائر غير متزامنة تعيد CompletableFuture:
navvo.geocodeAsync(GeocodeQuery.of("عمّان"));
navvo.routeAsync(req);
navvo.placeAsync("jordan-beans-cafe");
البناء بدون Maven
تُترجَم المكتبة بـ JDK وحده:
javac --release 11 -d build/classes $(find src/main/java -name '*.java')
jar --create --file navvo-java-0.1.0.jar -C build/classes .
java -cp navvo-java-0.1.0.jar io.navvo.examples.Main # اختبار سريع دون شبكة
ويُرفَق ملف pom.xml للنشر إلى Maven Central (mvn clean package يُنتج الحزمة
الثنائية وحِزمتَي -sources و-javadoc).
النشر والإصدار
تُنشَر الحزمة على Maven Central. الإصدار الحالي هو 0.1.0:
<dependency>
<groupId>io.navvo</groupId>
<artifactId>navvo-java</artifactId>
<version>0.1.0</version>
</dependency>