diff --git a/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/OpacApiFactory.java b/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/OpacApiFactory.java index 166bf098f..05848441c 100644 --- a/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/OpacApiFactory.java +++ b/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/OpacApiFactory.java @@ -43,6 +43,7 @@ import de.geeksfactory.opacclient.apis.VuFind; import de.geeksfactory.opacclient.apis.WebOpacNet; import de.geeksfactory.opacclient.apis.WinBiap; +import de.geeksfactory.opacclient.apis.Wise; import de.geeksfactory.opacclient.apis.Zones; import de.geeksfactory.opacclient.i18n.DummyStringProvider; import de.geeksfactory.opacclient.i18n.StringProvider; @@ -166,6 +167,8 @@ public static OpacApi create(Library lib, StringProvider sp, HttpClientFactory h newApiInstance = new BIB2(); } else if (lib.getApi().equals("test")) { newApiInstance = new TestApi(); + } else if (lib.getApi().equals("wise")) { + newApiInstance = new Wise(); } else { return null; } diff --git a/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/apis/OkHttpBaseApi.java b/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/apis/OkHttpBaseApi.java index 2f3e06bb6..83569a712 100644 --- a/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/apis/OkHttpBaseApi.java +++ b/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/apis/OkHttpBaseApi.java @@ -14,6 +14,7 @@ import java8.util.concurrent.CompletableFuture; import okhttp3.Call; import okhttp3.Callback; +import okhttp3.Interceptor; import okhttp3.MediaType; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -30,6 +31,7 @@ public abstract class OkHttpBaseApi extends BaseApi { public OkHttpClient http_client; public HttpClientFactory http_client_factory; protected boolean httpLoggingEnabled = true; + public Interceptor http_interceptor; /** * Initializes HTTP client and String Provider @@ -40,7 +42,9 @@ public void init(Library library, HttpClientFactory http_client_factory, boolean http_client = http_client_factory.getNewOkHttpClient( library.getData().optBoolean("customssl", false), library.getData().optBoolean("customssl_tls_only", true), - library.getData().optBoolean("customssl_all_ciphersuites", false) + library.getData().optBoolean("customssl_all_ciphersuites", false), + false, + http_interceptor ); http_client.dispatcher().setMaxRequestsPerHost(10); this.library = library; @@ -363,6 +367,17 @@ public String httpPost(String url, RequestBody data) return httpPost(url, data, getDefaultEncoding(), false); } + public void httpDelete(String url) throws IOException { + Request.Builder requestbuilder = new Request.Builder() + .url(cleanUrl(url)) + .header("Accept", "*/*") + .header("User-Agent", getUserAgent()); + + Request request = requestbuilder.delete().build(); + + Response response = http_client.newCall(request).execute(); + } + public void setHttpLoggingEnabled(boolean httpLoggingEnabled) { this.httpLoggingEnabled = httpLoggingEnabled; } diff --git a/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/apis/Wise.kt b/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/apis/Wise.kt new file mode 100644 index 000000000..2ba425652 --- /dev/null +++ b/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/apis/Wise.kt @@ -0,0 +1,563 @@ +package de.geeksfactory.opacclient.apis + +import de.geeksfactory.opacclient.i18n.StringProvider +import de.geeksfactory.opacclient.networking.HttpClientFactory +import de.geeksfactory.opacclient.networking.NotReachableException +import de.geeksfactory.opacclient.objects.* +import de.geeksfactory.opacclient.searchfields.BarcodeSearchField +import de.geeksfactory.opacclient.searchfields.DropdownSearchField +import de.geeksfactory.opacclient.searchfields.SearchField +import de.geeksfactory.opacclient.searchfields.SearchQuery +import de.geeksfactory.opacclient.utils.jsonObject +import okhttp3.Interceptor +import okhttp3.MediaType.Companion.toMediaTypeOrNull +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.Response +import org.json.JSONArray +import org.json.JSONException +import org.json.JSONObject +import java.util.* +import javax.crypto.Mac +import javax.crypto.spec.SecretKeySpec +import kotlin.experimental.and +import kotlin.math.floor + +data class Authentication(val libraryId: String, val patronSystemId: String,val token: String, val membershipExpiryDate: org.joda.time.LocalDate ) + +lateinit var apiKeyId: String +lateinit var apiKey: String +lateinit var applicationName: String +var auth: Authentication? = null + +/** + * OpacApi implementation for Wise owned by OCLC https://www.oclc.org/en/wise.html + * + * + * @author Henk Klijn Hesselink, April 2021 + */ + + +class WiseKeyInterceptor : Interceptor { + override fun intercept(chain: Interceptor.Chain): Response { + + val originalRequest = chain.request() + val requestBuilder = originalRequest.newBuilder() + .header("WISE_KEY", genWisekey()) + if ( auth != null) requestBuilder.addHeader("Authorization", auth!!.token) + val request = requestBuilder.build() + return chain.proceed(request) + } + + fun genWisekey(): String { + val epochDay: String = floor(Date().time / 8.64e7).toLong().toString() + val data = epochDay + applicationName + + val mac = Mac.getInstance("HmacSHA256") + val secret_key = SecretKeySpec(apiKey.toByteArray(charset("UTF-8")), "HmacSHA256") + mac.init(secret_key) + val signature= bytesToHex(mac.doFinal(data.toByteArray(charset("UTF-8")))) + return "$apiKeyId:$signature" + } + private val hexArray = "0123456789abcdef".toCharArray() + + fun bytesToHex(bytes: ByteArray): String { + val hexChars = CharArray(bytes.size * 2) + for (j in bytes.indices) { + var v = (bytes[j] and 0xFF.toByte()).toInt() + if ( v < 0) v = 256+v + + hexChars[j * 2] = hexArray[v ushr 4] + hexChars[j * 2 + 1] = hexArray[v and 0x0F] + } + return String(hexChars) + } +} + +open class Wise : OkHttpBaseApi() { + protected lateinit var baseurl: String + protected lateinit var imgurl: String + protected var searchLocations: List> = listOf(Pair("0","Own branch")) + protected var homeBranch: Long? = -1 + protected lateinit var libraryData: JSONObject + protected lateinit var queryString: String + protected lateinit var scope: String + protected var mediaTypeQS: String = "" + protected var vcgrpt: String = "" + protected lateinit var holdParameters: String + protected var pickupBranch: Long? = -1 + + protected val ENCODING = "UTF-8" + + private val mediatypes = mapOf( +// null to SearchResult.MediaType.UNKNOWN + "CD" to SearchResult.MediaType.CD, + "DVD" to SearchResult.MediaType.DVD, + "DVR" to SearchResult.MediaType.GAME_CONSOLE, + "CSP" to SearchResult.MediaType.GAME_CONSOLE, + "GBK" to SearchResult.MediaType.AUDIOBOOK, + "BOE" to SearchResult.MediaType.BOOK + ) + + private var itemstatuses: Map? = null + private var holdstatuses: Map? = null + + override fun init(library: Library, factory: HttpClientFactory, debug: Boolean) { + http_interceptor = WiseKeyInterceptor() + super.init(library, factory, debug) + libraryData = library.data + homeBranch = library.libraryId + baseurl = libraryData.getString("baseurl") + imgurl = libraryData.getString("imgurl") + val cats = libraryData.optJSONArray("search-locations") + if ( cats != null) { + val catsList = List(cats.length(),cats::getJSONObject) + searchLocations = emptyList() + catsList.forEach { + json -> val key = json.names()[0]; searchLocations = searchLocations + Pair(key as String, json.get(key) as String) + } + } + if ( libraryData.has("api-key-id") ) { + apiKeyId = libraryData.getString("api-key-id") + apiKey = libraryData.getString("api-key") + applicationName = libraryData.getString("app-name") + } + } + + override fun setStringProvider(stringProvider: StringProvider?) { + this.stringProvider = stringProvider + initStatuses() + } + + private fun initStatuses( ) { + itemstatuses = mapOf( + "available" to stringProvider.getString("available"), + "hold_allowed" to stringProvider.getString("hold_allowed"), + "reference" to stringProvider.getString("reference"), + "on_hold" to stringProvider.getString("on_hold"), + "on_loan" to stringProvider.getString("on_loan"), + "on_order" to stringProvider.getString("on_order"), + "not_available" to stringProvider.getString("not_available"), + "unknown" to stringProvider.getString("not_available") + ) + + + holdstatuses = mapOf( + "ACTIVE" to stringProvider.getString("ACTIVE"), + "CLOSED" to stringProvider.getString("CLOSED"), + "IN_TRANSPORT" to stringProvider.getString("IN_TRANSPORT"), + "LOANED" to stringProvider.getString("on_loan"), + "MESSAGE_SENT" to stringProvider.getString("reservation_ready"), + "RECIEVED" to stringProvider.getString("RECEIVED"), + "RECEIVED" to stringProvider.getString("RECEIVED"), + "RETURNED_TO_BRANCH" to stringProvider.getString("RETURNED_TO_BRANCH"), + "UNKNOWN" to stringProvider.getString("UNKNOWN") + ) + } + + override fun prolongAll(account: Account?, useraction: Int, selection: String?): OpacApi.ProlongAllResult { + TODO("Not yet implemented") + } + + override fun prolongMultiple(media: MutableList?, account: Account?, useraction: Int, selection: String?): OpacApi.ProlongAllResult { +// TODO("Not yet implemented") + return OpacApi.ProlongAllResult(OpacApi.MultiStepResult.Status.UNSUPPORTED) + } + + + protected fun parseSearchResult(fields: JSONObject): + SearchResult { + return SearchResult().apply { + val title = fields.getJSONObject("titel").getJSONObject("content").get("value") +// val year: Any? = fields.getJSONObject("pubjaar")?.getJSONObject("content")?.get("value") + val year = getFieldValue(fields.optJSONObject("pubjaar"), "label") + + val author = getFieldValue(fields.optJSONObject("auteur")) + val mediumSrt = getFieldValue(fields.getJSONObject("medium_srt")) + + innerhtml = "$title
${author ?: ""}
${year ?: ""}" + id = fields.getJSONObject("id").getJSONObject("content").get("value").toString() + cover = getImgUrl(getFieldValue(fields.optJSONObject("momkeys"))) + type = mediatypes[mediumSrt] + + } + } + + + private fun getFieldValue(fieldObject: JSONObject?, key: String = "value", flatten: Boolean = false): String? { + if (fieldObject == null) return null + + val contentObject = fieldObject.optJSONObject("content") + if (contentObject != null) { + return contentObject.getString(key) + } + val arr = fieldObject.optJSONArray("content") + if (arr != null && arr.length() > 0) { + if ( flatten) { + return List(arr.length(), arr::getJSONObject).map{ o -> o.getString(key) }.reduce{ u,v -> "$u, $v"} + } + return arr.getJSONObject(0).getString(key) + } + return null + } + + private fun getImgUrl(momkeys: String?, size: Int = 80): String? { + return "$baseurl${imgurl}size=${size}&$momkeys" + } + + override fun search(query: List): SearchRequestResult { + mediaTypeQS= "" + vcgrpt = "0" + query.forEach { q -> when(q.searchField.id){ + "materiaal" -> mediaTypeQS= "&wf_medium_srt=${q.value}" + "search" -> queryString = q.value.split(" ").reduce { u, v -> u + "%20" + v } + "searchScope" -> scope = q.value + "location" -> vcgrpt = q.value + } } + return searchGetPage(1) + } + + override fun searchGetPage(pagina: Int): SearchRequestResult { + val AMOUNT = 10 + val page = pagina -1 + val response = httpPost( + "$baseurl/cgi-bin/bx.pl", + ("prt=INTERNET&var=portal&vestnr=$homeBranch&fmt=json&search_in=$scope&amount=$AMOUNT&catalog=default&event=osearch" + + "&preset=all&offset=${page*AMOUNT}$mediaTypeQS&qs=$queryString&vcgrpf=0&backend=wise&vcgrpt=$vcgrpt").toRequestBody("application/x-www-form-urlencoded".toMediaTypeOrNull()), + ENCODING, false) + + val json = JSONObject(response) + val objects = List(json.getJSONArray("objects").length(), json.getJSONArray("objects")::getJSONObject) + val searchResultList = objects.map { o -> o.getJSONObject("fields") }.filter { fields -> getFieldValue(fields.getJSONObject("medium_srt")) != "Website" } .map { fields -> parseSearchResult(fields) } + + with(json.getJSONObject("paging")) { + return SearchRequestResult( + searchResultList, + getInt("total"), + getInt("total") / getInt("perpage"), + getInt("offset") / getInt("perpage") + ) + } + } + + + override fun cancel(media: String?, account: Account?, useraction: Int, selection: String?): OpacApi.CancelResult { + val itemId = media!!.split(":")[2] + + httpDelete("$baseurl/restapi/patron/${auth!!.patronSystemId}/library/${auth!!.libraryId}/hold/$itemId") + return OpacApi.CancelResult(OpacApi.MultiStepResult.Status.OK) + } + + override fun getShareUrl(id: String?, title: String?): String { + val titleId = id!!.split(":")[0] + return "$baseurl/wise-apps/catalog/$homeBranch/detail/wise/$titleId" + } + + override fun filterResults(filter: Filter?, option: Filter.Option?): SearchRequestResult { + TODO("Not yet implemented") + } + + override fun getSupportedLanguages(): MutableSet { + val langs: MutableSet = HashSet() + if (libraryData.has("languages")) { + try { + for (i in 0 until libraryData.getJSONArray("languages").length()) { + langs.add(libraryData.getJSONArray("languages").getString(i)) + } + } catch (e: JSONException) { + e.printStackTrace() + } + } + return langs + } + + override fun parseSearchFields(): List { + if (!initialised) start() + + val freeSearchField = BarcodeSearchField("search", stringProvider.getString("nav_search"), false,false,"") + val ietsTitelOrAuteur = DropdownSearchField().apply { + id = "searchScope" + displayName = stringProvider.getString("search_scope") + dropdownValues = listOf( + DropdownSearchField.Option("iets", stringProvider.getString("all")), + DropdownSearchField.Option("titel", stringProvider.getString("title")), + DropdownSearchField.Option("auteur", stringProvider.getString("author"))) + isAdvanced = false + } + + + val materiaal = DropdownSearchField().apply { + id = "materiaal" + displayName = stringProvider.getString("mediatype") + dropdownValues = listOf( + DropdownSearchField.Option("", stringProvider.getString("all")), + DropdownSearchField.Option("BOE", stringProvider.getString("mediatype_book")), + DropdownSearchField.Option("GBK", stringProvider.getString("mediatype_audiobook")), + DropdownSearchField.Option("CD", stringProvider.getString("mediatype_cd")), + DropdownSearchField.Option("DVD", stringProvider.getString("mediatype_dvd")) + ) + isAdvanced = false + } + if ( searchLocations.size > 1 ) { + val locations = DropdownSearchField().apply { + id = "location" + displayName = stringProvider.getString("location") + dropdownValues = searchLocations.map { (first, last) -> DropdownSearchField.Option(first, last) } + isAdvanced = false + } + return listOf(freeSearchField, ietsTitelOrAuteur, locations, materiaal) + } + return listOf(freeSearchField, ietsTitelOrAuteur, materiaal) + + } + + + override fun getSupportFlags(): Int { + return OpacApi.SUPPORT_FLAG_ENDLESS_SCROLLING or OpacApi + .SUPPORT_FLAG_WARN_RESERVATION_FEES or OpacApi.SUPPORT_FLAG_ACCOUNT_PROLONG_ALL + } + + override fun getResultById(id: String?, homebranch: String?): DetailedItem { + val titleId = id!!.split(":")[0] + val response = httpGet( + "$baseurl/cgi-bin/bx.pl?event=odetail&fmt=json&oid=$titleId&partials=about&pub=0&vestnr=$homeBranch", + ENCODING, false) + + val fields = JSONObject(response).getJSONObject("fields") + + + val omschr = Detail( "",getFieldValue(fields.optJSONObject("tt_info"))) +// val copys = getCopies(id,homebranch) + val copys: List = searchLocations.map { branchCatGroup -> getCopies(id,homebranch, branchCatGroup.first)}.fold(emptyList()){ + u, v -> listOf(u,v).flatten() + } + val firstItem = if (copys.isEmpty()) null else copys.filter { copy -> copy.status == itemstatuses!!["available"] }.firstOrNull() + val di = DetailedItem().apply { + title = getFieldValue(fields.getJSONObject("titel")) + cover = getImgUrl(getFieldValue(fields.optJSONObject("momkeys")),260) + val mediumSrt = getFieldValue(fields.getJSONObject("medium_srt")) + mediaType = mediatypes[mediumSrt] + copies = copys + isReservable = firstItem != null + reservation_info = if (isReservable) firstItem!!.barcode else null + + } + di.addDetail(omschr) + di.addDetail( Detail("Auteur", getFieldValue(fields.optJSONObject("auteur")), true )) + val medewerker = fields.optJSONObject("medewerker") + if ( medewerker != null ) di.addDetail( Detail("Medewerker", getFieldValue( fieldObject = fields.optJSONObject("medewerker"), flatten = true), true )) + val isbn = fields.optJSONObject("isbn") + if ( isbn != null ) di.addDetail( Detail("ISBN", getFieldValue(fields.optJSONObject("isbn")), true )) + val impressum = fields.optJSONObject("impressum") + if ( impressum != null ) di.addDetail( Detail("Uitgever", getFieldValue(fields.optJSONObject("impressum")), true )) + val ageCategory = fields.optJSONObject("leeftijd categorie") + if ( ageCategory != null ) di.addDetail( Detail("Leeftijd", getFieldValue(fields.optJSONObject("leeftijd categorie")), true )) + di.addDetail( Detail("Aanschafinfo", getFieldValue(fields.optJSONObject("aanschafinfo")), true )) + return di + } + + fun getCopies(titleIdAndPossibleItemId: String?, homebranch: String?, branchCatGroup: String): List { + + val titleId :String = titleIdAndPossibleItemId!!.split(":")[0] + + val url = "$baseurl/restapi/title/$titleId/iteminformation?branchCatGroups=$branchCatGroup&branchId=$homeBranch&clientType=I" + val itemArray: String = try { httpGet( + url, + ENCODING, false) + } catch (e: NotReachableException) { + "[]" + } + + val itemsInformation = JSONArray(itemArray) + val itemInformationList = List(itemsInformation.length(), itemsInformation::getJSONObject) + if (itemInformationList.isEmpty()) return emptyList() + + val copyList: List = itemInformationList.map{ item -> Copy().apply{ + branch = item.getString("branchName") + location = item.optString("subLocation") + barcode = item.optString("id") + }} + val items = copyList.map{ item -> item.barcode}.reduce { u,v -> "$u,$v" } + val respAvailable = httpGet( + "$baseurl/restapi/item/$items/availability", + ENCODING, false) + val arrayAvail = JSONArray(respAvailable) + val copyAvailList = List(arrayAvail.length(), arrayAvail::getJSONObject) + + for( copyAvail in copyAvailList) { + for(copy in copyList) { + if ( copy.barcode.equals(copyAvail["itemId"].toString())) { + val availStatus = (copyAvail["availabilityStatus"] as String).toLowerCase(Locale.getDefault()) + copy.status = itemstatuses!![availStatus] ?: itemstatuses!!["unknown"] + } + } + } + return copyList + } + + override fun reservation(item: DetailedItem, account: Account, useraction: Int, selection: String?): OpacApi.ReservationResult { + auth = login(account) + + if (useraction == 0 && selection == null) { + return OpacApi.ReservationResult(OpacApi.MultiStepResult.Status.SELECTION_NEEDED).apply { + actionIdentifier = OpacApi.ReservationResult.ACTION_USER + message = stringProvider.getString("pick_up_at_home") + this.selection = listOf(hashMapOf("key" to "Y","value" to "Ja"), hashMapOf("key" to "N","value" to stringProvider.getString("other_branch"))) + } + } else if (useraction == OpacApi.ReservationResult.ACTION_USER) { + val prepHold = httpGet("$baseurl/restapi/patron/${auth!!.patronSystemId}/library/${auth!!.libraryId}/preparehold/${item.id}/branch/$homeBranch", ENCODING).jsonObject + if ( selection == "N") { + // Select alternative branch + val pickupLocations = prepHold.getJSONArray("pickupLocations") + val plList = List( pickupLocations.length(), pickupLocations::getJSONObject) + + val plListOfMaps = plList.map { + pl -> hashMapOf( "key" to "${item.id}:${pl.getString("branchId")}:${pl.getString("description")}", + "value" to pl.getString("description") ) + } + return OpacApi.ReservationResult(OpacApi.MultiStepResult.Status.SELECTION_NEEDED).apply { + actionIdentifier = OpacApi.ReservationResult.ACTION_BRANCH + this.selection = plListOfMaps.sortedBy { a -> a.get("value")} + message = stringProvider.getString("alt_location") + } + } + val costs = prepHold.getDouble("reservationCost") + val queue = prepHold.optString("queuePosition") + holdParameters = prepHold.optString("holdParameters") + pickupBranch = homeBranch + + if ( costs < 0.000001 && queue == "") { + // Do reservation own branch free at costs + val jsonData = "{\"bibliographicRecordId\": \"${item.id}\", \"pickupLocationBranchId\":\"$homeBranch\", \"holdParameters\":\"$holdParameters\" }".toRequestBody(MEDIA_TYPE_JSON) + httpPost("$baseurl/restapi/patron/${auth!!.patronSystemId}/library/${auth!!.libraryId}/hold",jsonData, ENCODING).jsonObject + + return OpacApi.ReservationResult(OpacApi.MultiStepResult.Status.OK) + } + return OpacApi.ReservationResult(OpacApi.MultiStepResult.Status.CONFIRMATION_NEEDED).apply { + actionIdentifier = OpacApi.ReservationResult.ACTION_CONFIRMATION + details = listOf( arrayOf("Kosten", costs.toString()), arrayOf("Wachtrij positie", queue)) + message = stringProvider.getString("cost_queue") + } + + } else if (useraction == OpacApi.ReservationResult.ACTION_BRANCH) { + pickupBranch = selection!!.split(":")[1].toLong() + val prepHold = httpGet("$baseurl/restapi/patron/${auth!!.patronSystemId}/library/${auth!!.libraryId}/preparehold/${item.id}/branch/$pickupBranch", ENCODING).jsonObject + val costs = prepHold.getString("reservationCost") + val queue = prepHold.optString("queuePosition") + holdParameters = prepHold.optString("holdParameters") + // Confirm Fee and queue + return OpacApi.ReservationResult(OpacApi.MultiStepResult.Status.CONFIRMATION_NEEDED).apply { + actionIdentifier = OpacApi.ReservationResult.ACTION_CONFIRMATION + details = listOf(arrayOf("Ophaallocatie", selection.split(":")[2]), arrayOf("Kosten", costs.toString()), arrayOf("Wachtrij positie", queue)) + message = stringProvider.getString("pickup_location") + } + } else if (useraction == OpacApi.ReservationResult.ACTION_CONFIRMATION) { + // Do reservation at pickup branch with possible fees + val jsonData = "{\"bibliographicRecordId\": \"${item.id}\", \"pickupLocationBranchId\":\"$pickupBranch\", \"holdParameters\":\"$holdParameters\" }".toRequestBody(MEDIA_TYPE_JSON) + httpPost("$baseurl/restapi/patron/${auth!!.patronSystemId}/library/${auth!!.libraryId}/hold",jsonData, ENCODING).jsonObject + + return OpacApi.ReservationResult(OpacApi.MultiStepResult.Status.OK) + } else { + return OpacApi.ReservationResult(OpacApi.MultiStepResult.Status.ERROR) + } + } + + override fun setLanguage(language: String?) { + + } + + override fun prolong(media: String?, account: Account?, useraction: Int, selection: String?): OpacApi.ProlongResult { + val itemId = media!!.split(":")[1] + httpPost("$baseurl/restapi/patron/${auth!!.patronSystemId}/item/${itemId}/loanrenewal", + "{}".toRequestBody(MEDIA_TYPE_JSON), + ENCODING).jsonObject + return OpacApi.ProlongResult(OpacApi.MultiStepResult.Status.OK) + } + + override fun account(account: Account): AccountData { + auth = login(account) + + val loans = httpGet("$baseurl/restapi/patron/${auth!!.patronSystemId}/library/${auth!!.libraryId}/loan", ENCODING).jsonObject + val holds = httpGet("$baseurl/restapi/patron/${auth!!.patronSystemId}/library/${auth!!.libraryId}/hold", ENCODING).jsonObject + val feeAndFines = httpGet("$baseurl/restapi/patron/${auth!!.patronSystemId}/fee", ENCODING).jsonObject.getJSONArray("items") + val itemsList = List( feeAndFines.length(), feeAndFines::getJSONObject) + val fee = itemsList.map { item -> item.getDouble("amount")/100 }.fold(0.0){ x,y -> x+y} + + return AccountData(account.id).apply { + pendingFees = fee.toString() + lent = parseLent(loans.getJSONArray("items")) + reservations = parseHolds(holds.getJSONArray("items")) + validUntil = auth!!.membershipExpiryDate.toString() + } + } + + private fun parseHolds(holds: JSONArray): List { + val items = List(holds.length(), holds::getJSONObject) + return items.map { item -> + ReservedItem().apply { + id = item.getString("bibliographicRecordId") + ":" + item.getString("holdNumber") + ":" + item.getString("id") // combine title id, copy id an hold id + title = item.getString("title") + author = item.getString("author") + mediaType = mediatypes[item.getString("medium")] + cover = getImgUrl(item.getString("momkeys").replace(';', '&')) + branch = item.getString("pickupLocationName") + status = holdstatuses!![item.getString("holdStatus").toUpperCase(Locale.getDefault())] ?: holdstatuses!!["UNKNOWN"] + if (item.getBoolean("cancelAllowed")) cancelData = id + dbId = item.getLong("itemId") + if (item.getBoolean("awaitingPickup")) readyDate = org.joda.time.LocalDate.parse(item.getString("holdDueDate")) + if (false && item.getBoolean("updateAllowed")) bookingData = id + + } + } + } + + internal fun parseLent(json: JSONArray): List { + val items = List(json.length(), json::getJSONObject) + return items.map { item -> LentItem().apply { + id = item.getString("bibliographicRecordId") + ":" + item.getString("itemId") // combine title id and copy id + title = item.getString("title") + author = item.getString("author") + mediaType = mediatypes[item.getString("medium")] + cover = getImgUrl(item.getString("momkeys").replace(';', '&')) + lendingBranch = item.getString("branchId") + // TODO cache branch names + val response = httpGet("$baseurl/restapi/branch/$lendingBranch", ENCODING).jsonObject + + if (response.optString("name") != "") lendingBranch = response.get("name") as String + val dueDate = org.joda.time.LocalDate.parse(item.getString("dueDate")) + deadline = dueDate + isRenewable = item.getBoolean("itemRenewable") + val s = item.optString("newDueDate") + if ( s != "") { + val newDueDate = org.joda.time.LocalDate.parse(s) + if ( newDueDate.isAfter(dueDate)) prolongData = id + } + } } + } + + + override fun checkAccountData(account: Account) { + auth = login(account) + } + + fun login(account: Account) : Authentication { + val jsonData = "{\"username\": \"${account.name}\", \"password\":\"${account.password}\" }".toRequestBody(MEDIA_TYPE_JSON) + val authenicateCall = httpPost("$baseurl/restapi/patron/authentication",jsonData, ENCODING) + + val response = JSONObject(authenicateCall) + return Authentication( + token = response.getString("token"), + libraryId = response.getString("libraryId"), + patronSystemId = response.getString("patronSystemId"), + membershipExpiryDate = org.joda.time.LocalDate.parse(response.getString("membershipExpiryDate")) + ) + } + + override fun getResult(position: Int): DetailedItem { + TODO("Not yet implemented") + } + + override fun shouldUseMeaningDetector(): Boolean { + return false + } + +} diff --git a/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/networking/HttpClientFactory.java b/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/networking/HttpClientFactory.java index c84332178..72f94e461 100644 --- a/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/networking/HttpClientFactory.java +++ b/opacclient/libopac/src/main/java/de/geeksfactory/opacclient/networking/HttpClientFactory.java @@ -37,6 +37,7 @@ import java.io.InputStream; import java.net.CookieManager; import java.net.CookiePolicy; +import java.net.Proxy; import java.net.URI; import java.net.URISyntaxException; import java.security.KeyManagementException; @@ -162,7 +163,7 @@ public HttpClient getNewApacheHttpClient(boolean customssl, boolean tls_only, public OkHttpClient getNewOkHttpClient(boolean customssl, boolean tls_only, boolean allCipherSuites) { - return getOkHttpClientBuilder(customssl, tls_only, allCipherSuites, false).build(); + return getOkHttpClientBuilder(customssl, tls_only, allCipherSuites, false, null).build(); } /** @@ -177,12 +178,21 @@ public OkHttpClient getNewOkHttpClient(boolean customssl, boolean tls_only, boolean allCipherSuites, boolean ellipticCurvesWorkaround) { return getOkHttpClientBuilder(customssl, tls_only, allCipherSuites, - ellipticCurvesWorkaround).build(); + ellipticCurvesWorkaround, null).build(); + } + + public OkHttpClient getNewOkHttpClient(boolean customssl, boolean tls_only, + boolean allCipherSuites, + boolean ellipticCurvesWorkaround, + Interceptor interceptor) { + return getOkHttpClientBuilder(customssl, tls_only, allCipherSuites, + ellipticCurvesWorkaround, interceptor).build(); } protected OkHttpClient.Builder getOkHttpClientBuilder(boolean customssl, boolean tls_only, boolean allCipherSuites, - boolean ellipticCurvesWorkaround) { + boolean ellipticCurvesWorkaround, + Interceptor interceptor) { OkHttpClient.Builder builder = new OkHttpClient.Builder(); CookieManager cookieManager = new CookieManager(); @@ -193,6 +203,8 @@ protected OkHttpClient.Builder getOkHttpClientBuilder(boolean customssl, boolean builder.connectTimeout(60, TimeUnit.SECONDS); builder.readTimeout(60, TimeUnit.SECONDS); builder.writeTimeout(60, TimeUnit.SECONDS); + builder.proxy(Proxy.NO_PROXY); + if (interceptor != null) builder.addInterceptor(interceptor); if (customssl && ssl_store_path != null) { try { diff --git a/opacclient/libopac/src/test/java/de/geeksfactory/opacclient/apis/WiseTest.kt b/opacclient/libopac/src/test/java/de/geeksfactory/opacclient/apis/WiseTest.kt new file mode 100644 index 000000000..f24eeb879 --- /dev/null +++ b/opacclient/libopac/src/test/java/de/geeksfactory/opacclient/apis/WiseTest.kt @@ -0,0 +1,61 @@ +package de.geeksfactory.opacclient.apis + +import de.geeksfactory.opacclient.networking.HttpClientFactory +import de.geeksfactory.opacclient.objects.Account +import de.geeksfactory.opacclient.objects.DetailedItem +import de.geeksfactory.opacclient.objects.Library +import de.geeksfactory.opacclient.searchfields.SearchQuery +import de.geeksfactory.opacclient.searchfields.TextSearchField +import org.json.JSONArray +import org.json.JSONObject +import org.junit.Assert.assertTrue +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.Parameterized +import org.mockito.Mockito +import java.util.* + +@RunWith(Parameterized::class) +class WiseTest(private val file: String) : BaseHtmlTest() { + val wise = Mockito.spy(Wise::class.java) + + init { + wise.init(Library().apply { + data = JSONObject().apply { + put("baseurl", "https://catalogus.biblionetdrenthe.nl") + put("imgurl", "/cgi-bin/momredir.pl?") + put("api-key-id", "4251d316-b964-44cc-b5fc-2f888d3716a8") + put("api-key", "218f81af-dcab-4cca-97f3-a4cffe19a0c9") + put("app-name", "WiseCatPlus") + put("search-locations", JSONArray("[{\"0\" : \"in jouw bibliotheek\"}, {\"2\" : \"in de provincie\"}]")) + put("languages", listOf("nl","de")) + } + libraryId = 9585 + }, HttpClientFactory("test")) + } + + @Test + fun testResult() { + val json = JSONObject(readResource("/wise/result/$file")) + + val objects = json.getJSONArray("objects") + + assertTrue(objects.length() > 0) + + } + + + companion object { + + private val FILES = arrayOf("assen.json") + + @JvmStatic + @Parameterized.Parameters(name = "{0}") + fun files(): Collection> { + val files = ArrayList>() + for (file in FILES) { + files.add(arrayOf(file)) + } + return files + } + }} diff --git a/opacclient/libopac/src/test/resources/wise/result/assen.json b/opacclient/libopac/src/test/resources/wise/result/assen.json new file mode 100644 index 000000000..8d134c2e9 --- /dev/null +++ b/opacclient/libopac/src/test/resources/wise/result/assen.json @@ -0,0 +1,3402 @@ +{ + "actual": { + "drilldowns": [], + "sorting": { + "sortkey": "relevantie", + "sortorder": "desc" + } + }, + "version": "1.0", + "paging": { + "amount": 10, + "total": "337", + "perpage": "10", + "offset": "0" + }, + "sortings": [ + { + "orders": { + "value": [ + { + "value": "desc", + "label": "WCP-BACKEND__SORTORDER-DESCENDING" + } + ], + "code": "sortorder" + }, + "value": "relevantie", + "label": "WCP-BACKEND__SORTBY-RELEVANCE" + }, + { + "orders": { + "value": [ + { + "value": "desc", + "label": "WCP-BACKEND__SORTORDER-DESCENDING" + }, + { + "value": "asc", + "label": "WCP-BACKEND__SORTORDER-ASCENDING" + } + ], + "code": "sortorder" + }, + "value": "populariteit", + "label": "WCP-BACKEND__SORTBY-POPULARITY" + }, + { + "orders": { + "value": [ + { + "value": "asc", + "label": "WCP-BACKEND__SORTORDER-ASCENDING" + }, + { + "value": "desc", + "label": "WCP-BACKEND__SORTORDER-DESCENDING" + } + ], + "code": "sortorder" + }, + "value": "titel", + "label": "WCP-BACKEND__SORTBY-TITLE" + }, + { + "orders": { + "value": [ + { + "value": "asc", + "label": "WCP-BACKEND__SORTORDER-ASCENDING" + }, + { + "value": "desc", + "label": "WCP-BACKEND__SORTORDER-DESCENDING" + } + ], + "code": "sortorder" + }, + "value": "auteur", + "label": "WCP-BACKEND__SORTBY-AUTHOR" + }, + { + "orders": { + "value": [ + { + "value": "desc", + "label": "WCP-BACKEND__SORTORDER-DESCENDING" + }, + { + "value": "asc", + "label": "WCP-BACKEND__SORTORDER-ASCENDING" + } + ], + "code": "sortorder" + }, + "value": "datum", + "label": "WCP-BACKEND__SORTBY-DATE" + } + ], + "backend": "wise", + "params": {}, + "drilldowns": [ + { + "order": 99, + "filters": [ + { + "amount": "253", + "value": "BOE", + "label": "Boek" + }, + { + "amount": "74", + "value": "DVD", + "label": "DVD-Video" + }, + { + "amount": "4", + "value": "GLB", + "label": "GROTE LETTER" + }, + { + "amount": "3", + "value": "Film", + "label": "Film" + }, + { + "amount": "2", + "value": "Website", + "label": "Website" + }, + { + "amount": "1", + "value": "GBK", + "label": "Luisterboek" + } + ], + "label": "WCP-BACKEND__DRILLDOWNS-MEDIUMSOORT", + "code": "wf_medium_srt" + }, + { + "order": 99, + "filters": [ + { + "amount": "195", + "value": "3", + "label": "Volwassen Informatief" + }, + { + "amount": "96", + "value": "2", + "label": "Volwassen Verhalend" + }, + { + "amount": "37", + "value": "4", + "label": "Jeugd Verhalend" + }, + { + "amount": "10", + "value": "5", + "label": "Jeugd Informatief" + } + ], + "label": "WCP-BACKEND__DRILLDOWNS-TYPING", + "code": "wf_typering" + }, + { + "order": 99, + "filters": [ + { + "amount": "40", + "value": "TH", + "label": "Thriller" + }, + { + "amount": "30", + "value": "OO", + "label": "Oorlog" + }, + { + "amount": "30", + "value": "PS", + "label": "Psychologisch " + }, + { + "amount": "13", + "value": "HI", + "label": "Historisch" + }, + { + "amount": "13", + "value": "SO", + "label": "Sociale problematiek" + }, + { + "amount": "12", + "value": "DE", + "label": "Detective" + }, + { + "amount": "12", + "value": "FA", + "label": "Familie" + }, + { + "amount": "12", + "value": "PO", + "label": "Politiek verhaal" + }, + { + "amount": "9", + "value": "RO", + "label": "Romantisch" + }, + { + "amount": "6", + "value": "SP", + "label": "Spionage" + }, + { + "amount": "5", + "value": "BI", + "label": "Biografie" + }, + { + "amount": "4", + "value": "DI", + "label": "Dierenleven" + }, + { + "amount": "3", + "value": "HU", + "label": "Humoristisch" + }, + { + "amount": "3", + "value": "PR", + "label": "Protestants milieu" + }, + { + "amount": "3", + "value": "RK", + "label": "Rooms-katholiek milieu" + }, + { + "amount": "3", + "value": "SK", + "label": "Sprookjes" + }, + { + "amount": "3", + "value": "VH", + "label": "Verhalenbundel" + }, + { + "amount": "2", + "value": "FE", + "label": "Feministische verhalen" + }, + { + "amount": "2", + "value": "KI", + "label": "Kinderleven" + }, + { + "amount": "2", + "value": "SC", + "label": "Schoolverhaal" + }, + { + "amount": "2", + "value": "SF", + "label": "Science fiction" + }, + { + "amount": "2", + "value": "ST", + "label": "Stripverhaal" + }, + { + "amount": "1", + "value": "AV", + "label": "Avonturenverhaal" + }, + { + "amount": "1", + "value": "ER", + "label": "Erotische verhalen" + }, + { + "amount": "1", + "value": "KE", + "label": "Kerstverhaal" + }, + { + "amount": "1", + "value": "PA", + "label": "Paasverhaal" + }, + { + "amount": "1", + "value": "RA", + "label": "Rassenvraagstuk" + }, + { + "amount": "1", + "value": "SB", + "label": "Streek- en boeren" + }, + { + "amount": "1", + "value": "SR", + "label": "Sport" + }, + { + "amount": "1", + "value": "VZ", + "label": "Verzet" + } + ], + "label": "WCP-BACKEND__DRILLDOWNS-GENRE", + "code": "wf_genre_rub" + }, + { + "order": 3, + "filters": [ + { + "amount": "263", + "value": "DUT", + "label": "Nederlands" + }, + { + "amount": "34", + "value": "ENG", + "label": "Engels" + }, + { + "amount": "24", + "value": "GER", + "label": "Duits" + }, + { + "amount": "15", + "value": "FRE", + "label": "Frans" + }, + { + "amount": "6", + "value": "ITA", + "label": "Italiaans" + }, + { + "amount": "5", + "value": "MUL", + "label": "Meerdere talen" + }, + { + "amount": "2", + "value": "SWE", + "label": "Zweeds" + }, + { + "amount": "1", + "value": "DAN", + "label": "Deens" + }, + { + "amount": "1", + "value": "GSW", + "label": "Zwitserduits" + }, + { + "amount": "1", + "value": "HEB", + "label": "Hebreews" + }, + { + "amount": "1", + "value": "HUN", + "label": "Hongaars" + }, + { + "amount": "1", + "value": "JPN", + "label": "Japans" + }, + { + "amount": "1", + "value": "LIN", + "label": "Lingala" + }, + { + "amount": "1", + "value": "PER", + "label": "Perzisch, modern (Farsi)" + }, + { + "amount": "1", + "value": "SPA", + "label": "Spaans" + } + ], + "label": "WCP-BACKEND__DRILLDOWNS-LANGUAGE", + "code": "wf_taal" + }, + { + "order": 99, + "filters": [ + { + "amount": "4", + "value": "National Geographic reisgids", + "label": "National Geographic reisgids" + }, + { + "amount": "3", + "value": "Cossee century", + "label": "Cossee century" + }, + { + "amount": "3", + "value": "Grote letter bibliotheek", + "label": "Grote letter bibliotheek" + }, + { + "amount": "3", + "value": "Rainbow pocketboeken", + "label": "Rainbow pocketboeken" + }, + { + "amount": "3", + "value": "Toeristische gids", + "label": "Toeristische gids" + }, + { + "amount": "2", + "value": "Capitool reisgidsen", + "label": "Capitool reisgidsen" + }, + { + "amount": "2", + "value": "De collectie", + "label": "De collectie" + }, + { + "amount": "2", + "value": "Lumière series", + "label": "Lumière series" + }, + { + "amount": "2", + "value": "Michel Junior-Katalog ...", + "label": "Michel Junior-Katalog ..." + }, + { + "amount": "2", + "value": "Trotter", + "label": "Trotter" + }, + { + "amount": "1", + "value": "100%", + "label": "100%" + }, + { + "amount": "1", + "value": "360° reizen", + "label": "360° reizen" + }, + { + "amount": "1", + "value": "ANWB extra", + "label": "ANWB extra" + }, + { + "amount": "1", + "value": "Atlantis ongezonken", + "label": "Atlantis ongezonken" + }, + { + "amount": "1", + "value": "Buchfinken. HAVO/VWO", + "label": "Buchfinken. HAVO/VWO" + }, + { + "amount": "1", + "value": "Capitool compact", + "label": "Capitool compact" + }, + { + "amount": "1", + "value": "Capitool reisgidsen top 10", + "label": "Capitool reisgidsen top 10" + }, + { + "amount": "1", + "value": "Coolman en ik", + "label": "Coolman en ik" + }, + { + "amount": "1", + "value": "Cossee essay", + "label": "Cossee essay" + }, + { + "amount": "1", + "value": "Crime series", + "label": "Crime series" + }, + { + "amount": "1", + "value": "De leeslijst : tien Nederlandse klassiekers", + "label": "De leeslijst : tien Nederlandse klassiekers" + }, + { + "amount": "1", + "value": "Dominicus reeks", + "label": "Dominicus reeks" + }, + { + "amount": "1", + "value": "Eagle : de tweekoppige adelaar", + "label": "Eagle : de tweekoppige adelaar" + }, + { + "amount": "1", + "value": "Elsevier. Speciale editie", + "label": "Elsevier. Speciale editie" + }, + { + "amount": "1", + "value": "Geschenk", + "label": "Geschenk" + }, + { + "amount": "1", + "value": "Gouden boekjes", + "label": "Gouden boekjes" + }, + { + "amount": "1", + "value": "Groene gids weekend", + "label": "Groene gids weekend" + }, + { + "amount": "1", + "value": "Heimat Trilogie", + "label": "Heimat Trilogie" + }, + { + "amount": "1", + "value": "Het Mysterium", + "label": "Het Mysterium" + }, + { + "amount": "1", + "value": "KiWi", + "label": "KiWi" + }, + { + "amount": "1", + "value": "Lebowski book of the month", + "label": "Lebowski book of the month" + }, + { + "amount": "1", + "value": "Lees-mij!", + "label": "Lees-mij!" + }, + { + "amount": "1", + "value": "LoveStory", + "label": "LoveStory" + }, + { + "amount": "1", + "value": "Ludwig Licht-kwartet", + "label": "Ludwig Licht-kwartet" + }, + { + "amount": "1", + "value": "Maaike & Domenico", + "label": "Maaike & Domenico" + }, + { + "amount": "1", + "value": "Mannen van de wereld", + "label": "Mannen van de wereld" + }, + { + "amount": "1", + "value": "Marco Polo", + "label": "Marco Polo" + }, + { + "amount": "1", + "value": "Merian live!", + "label": "Merian live!" + }, + { + "amount": "1", + "value": "Monografieën van Nederlandse fotografen", + "label": "Monografieën van Nederlandse fotografen" + }, + { + "amount": "1", + "value": "Oorzaak & gevolg", + "label": "Oorzaak & gevolg" + }, + { + "amount": "1", + "value": "Op wereldreis met Ben en Polo", + "label": "Op wereldreis met Ben en Polo" + }, + { + "amount": "1", + "value": "Parel pockets", + "label": "Parel pockets" + }, + { + "amount": "1", + "value": "Pasolini collection", + "label": "Pasolini collection" + }, + { + "amount": "1", + "value": "Quality film collection", + "label": "Quality film collection" + }, + { + "amount": "1", + "value": "Ravn reeks", + "label": "Ravn reeks" + }, + { + "amount": "1", + "value": "Rosa & co", + "label": "Rosa & co" + }, + { + "amount": "1", + "value": "Sniper-serie", + "label": "Sniper-serie" + }, + { + "amount": "1", + "value": "Streetwise", + "label": "Streetwise" + }, + { + "amount": "1", + "value": "The century trilogy", + "label": "The century trilogy" + }, + { + "amount": "1", + "value": "The cruelty", + "label": "The cruelty" + }, + { + "amount": "1", + "value": "The house of crime", + "label": "The house of crime" + }, + { + "amount": "1", + "value": "Thriller", + "label": "Thriller" + }, + { + "amount": "1", + "value": "Tien Nederlandse klassiekers", + "label": "Tien Nederlandse klassiekers" + }, + { + "amount": "1", + "value": "Time to momo", + "label": "Time to momo" + }, + { + "amount": "1", + "value": "Verboden-voor-ouders", + "label": "Verboden-voor-ouders" + }, + { + "amount": "1", + "value": "Verder kijken", + "label": "Verder kijken" + }, + { + "amount": "1", + "value": "Wandelgidsen", + "label": "Wandelgidsen" + }, + { + "amount": "1", + "value": "Wereldoorlog II, de grote slagen", + "label": "Wereldoorlog II, de grote slagen" + }, + { + "amount": "1", + "value": "Wereldsteden", + "label": "Wereldsteden" + }, + { + "amount": "1", + "value": "XL", + "label": "XL" + }, + { + "amount": "1", + "value": "Young & quality films", + "label": "Young & quality films" + }, + { + "amount": "1", + "value": "Zwarte beertjes", + "label": "Zwarte beertjes" + } + ], + "label": "WCP-BACKEND__DRILLDOWNS-SERIES", + "code": "wf_reeks_serie" + }, + { + "volatile": 1, + "order": 99, + "filters": [ + { + "amount": "4", + "value": "Bomann, Corina", + "label": "Bomann, Corina" + }, + { + "amount": "4", + "value": "Caris, Lilian", + "label": "Caris, Lilian" + }, + { + "amount": "4", + "value": "Schippers, Elly", + "label": "Schippers, Elly" + }, + { + "amount": "3", + "value": "Christiane F.", + "label": "Christiane F." + }, + { + "amount": "3", + "value": "Danes, Claire", + "label": "Danes, Claire" + }, + { + "amount": "3", + "value": "Döblin, Alfred", + "label": "Döblin, Alfred" + }, + { + "amount": "3", + "value": "Fallada, Hans", + "label": "Fallada, Hans" + }, + { + "amount": "3", + "value": "Fitzek, Sebastian", + "label": "Fitzek, Sebastian" + }, + { + "amount": "3", + "value": "Gerretzen, Ellen", + "label": "Gerretzen, Ellen" + }, + { + "amount": "3", + "value": "Glanfield, Jenny", + "label": "Glanfield, Jenny" + }, + { + "amount": "3", + "value": "Hauth-Grubben, Goverdien", + "label": "Hauth-Grubben, Goverdien" + }, + { + "amount": "3", + "value": "Kerr, Philip", + "label": "Kerr, Philip" + }, + { + "amount": "3", + "value": "Nes, Liesbeth van", + "label": "Nes, Liesbeth van" + }, + { + "amount": "3", + "value": "Patinkin, Mandy", + "label": "Patinkin, Mandy" + }, + { + "amount": "3", + "value": "Peters, Maria", + "label": "Peters, Maria" + } + ], + "label": "WCP-BACKEND__DRILLDOWNS-AUTHOR", + "code": "wf_auteur_facet" + }, + { + "volatile": 1, + "order": 99, + "filters": [ + { + "amount": "52", + "value": "Berlijn", + "label": "Berlijn" + }, + { + "amount": "36", + "value": "Wereldoorlog II", + "label": "Wereldoorlog II" + }, + { + "amount": "27", + "value": "Duitsland", + "label": "Duitsland" + }, + { + "amount": "27", + "value": "Reisgidsen", + "label": "Reisgidsen" + }, + { + "amount": "16", + "value": "Verhalen", + "label": "Verhalen" + }, + { + "amount": "7", + "value": "Jodenvervolging", + "label": "Jodenvervolging" + }, + { + "amount": "6", + "value": "Nederland", + "label": "Nederland" + }, + { + "amount": "5", + "value": "20e eeuw", + "label": "20e eeuw" + }, + { + "amount": "5", + "value": "DDR", + "label": "DDR" + }, + { + "amount": "5", + "value": "Europa", + "label": "Europa" + }, + { + "amount": "5", + "value": "Geschiedenis", + "label": "Geschiedenis" + }, + { + "amount": "5", + "value": "Homoseksuele mannen", + "label": "Homoseksuele mannen" + }, + { + "amount": "5", + "value": "Waargebeurd", + "label": "Waargebeurd" + }, + { + "amount": "4", + "value": "Biografieën", + "label": "Biografieën" + }, + { + "amount": "4", + "value": "Hitler, Adolf", + "label": "Hitler, Adolf" + } + ], + "label": "WCP-BACKEND__DRILLDOWNS-SUBJECT", + "code": "wf_onderwerp" + }, + { + "order": 2, + "filters": [ + { + "amount": "1", + "value": "[2021-01-01T00:00:00Z TO 2021-01-01T00:00:00Z+1YEAR]", + "label": "2021" + }, + { + "amount": "23", + "value": "[2020-01-01T00:00:00Z TO 2020-01-01T00:00:00Z+1YEAR]", + "label": "2020" + }, + { + "amount": "31", + "value": "[2019-01-01T00:00:00Z TO 2019-01-01T00:00:00Z+1YEAR]", + "label": "2019" + }, + { + "amount": "38", + "value": "[2018-01-01T00:00:00Z TO 2018-01-01T00:00:00Z+1YEAR]", + "label": "2018" + }, + { + "amount": "47", + "value": "[2017-01-01T00:00:00Z TO 2017-01-01T00:00:00Z+1YEAR]", + "label": "2017" + }, + { + "amount": "37", + "value": "[2016-01-01T00:00:00Z TO 2016-01-01T00:00:00Z+1YEAR]", + "label": "2016" + }, + { + "amount": "155", + "value": "[* TO 2016-01-01T00:00:00Z]", + "label": "2016 >" + } + ], + "label": "WCP-BACKEND__DRILLDOWNS-PUBYEAR", + "code": "wf_pubjaar" + } + ], + "timing": {}, + "objects": [ + { + "field_display_order": [ + "auteur", + "onderwerp", + "cwisenr", + "tt_info", + "momkeys", + "titel", + "pubjaar", + "reeks_serie", + "typering", + "materiaal", + "pim", + "vestcatgrp", + "ovrg_aut", + "siso", + "icon_media", + "medium_srt", + "t1_hoog", + "t1_midden", + "bron_naam", + "origine", + "origin_id", + "detail_type", + "detail_uri", + "id" + ], + "version": "2.0", + "backend": "wise", + "availability": [], + "fields": { + "detail_type": { + "content": [ + { + "value": "detail" + } + ], + "label": "detail_type" + }, + "momkeys": { + "content": { + "value": "lid=2018072629;ppn=416723632;isbn=9789057678400;key=1164821;" + }, + "label": "momkeys" + }, + "ovrg_aut": { + "content": [ + { + "value": "Hoogen, Vincent van den", + "code": "31409644" + }, + { + "value": "Harms, Laurence", + "code": "41313027" + } + ], + "label": "medewerker" + }, + "medium_srt": { + "content": { + "value": "BOE", + "label": "Boek" + }, + "label": "medium" + }, + "auteur": { + "content": [ + { + "value": "Ours, Maartje van", + "label": "Ours, Maartje van", + "code": "40660277" + } + ], + "label": "auteur" + }, + "bron_naam": { + "content": [ + { + "value": "wise" + } + ], + "label": "bron_naam" + }, + "reeks_serie": { + "content": [ + { + "value": "Time to momo", + "label": "Time to momo", + "code": "1768764240" + } + ], + "label": "reeks/serie" + }, + "cwisenr": { + "content": [ + { + "value": "10008998" + } + ], + "label": "cwisenr" + }, + "t1_hoog": { + "content": [ + { + "value": "Time to momo Berlijn" + } + ], + "label": "t1_hoog" + }, + "materiaal": { + "content": [ + { + "value": "IV" + } + ], + "label": "materiaal" + }, + "titel": { + "content": { + "value": "Time to momo Berlijn" + }, + "label": "titel" + }, + "id": { + "content": { + "value": "1164821" + }, + "label": "id" + }, + "pim": { + "content": [ + { + "value": "18" + } + ], + "label": "pim" + }, + "icon_media": { + "content": { + "value": "book", + "label": "Boek" + }, + "label": "icon_media" + }, + "t1_midden": { + "content": [ + { + "value": "Berlijn" + } + ], + "label": "t1_midden" + }, + "typering": { + "content": [ + { + "value": "2" + } + ], + "label": "typering" + }, + "origin_id": { + "content": [ + { + "value": "1164821" + } + ], + "label": "origin_id" + }, + "vestcatgrp": { + "content": [ + { + "value": 0 + } + ], + "label": "vestcatgrp" + }, + "tt_info": { + "content": { + "value": "Deze oorspronkelijk Nederlandstalige reisgids in zakformaat over Berlijn heeft een nieuw uiterlijk gekregen en heet geen 100% meer maar 'Time to momo'. Aan ..." + }, + "label": "beschrijving" + }, + "siso": { + "content": [ + { + "value": "996.3 Duitsland", + "code": "1765847665" + } + ], + "label": "siso" + }, + "origine": { + "content": { + "value": "wise" + }, + "label": "origine" + }, + "pubjaar": { + "content": { + "label": "2018" + }, + "label": "pubjaar" + }, + "onderwerp": { + "content": [ + { + "value": "Berlijn", + "label": "Berlijn", + "code": "7798507" + }, + { + "value": "Reisgidsen", + "label": "Reisgidsen", + "code": "7797390" + } + ], + "label": "onderwerp" + }, + "detail_uri": { + "content": [ + { + "value": "?sid=414baf2f-729b-4191-a8a7-9919af9b25ef;vestnr=9585;prt=INTERNET;fmt=json;var=portal;event=odetail;backend=wise;oid=1164821" + } + ], + "label": "detail_uri" + } + }, + "controls": [ + { + "params": { + "titcode": "1164821", + "event": "favadd" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-FAVLIST-ADD", + "type": "mark" + }, + { + "params": { + "titcode": "1164821", + "event": "rsrvrqn" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-RESERVE", + "type": "acquire" + } + ], + "editions": [], + "labels": [] + }, + { + "field_display_order": [ + "auteur", + "onderwerp", + "cwisenr", + "tt_info", + "momkeys", + "titel", + "pubjaar", + "reeks_serie", + "typering", + "materiaal", + "pim", + "vestcatgrp", + "ovrg_aut", + "siso", + "icon_media", + "medium_srt", + "t1_hoog", + "t1_midden", + "bron_naam", + "origine", + "origin_id", + "detail_type", + "detail_uri", + "id" + ], + "version": "2.0", + "backend": "wise", + "availability": [], + "fields": { + "detail_type": { + "content": [ + { + "value": "detail" + } + ], + "label": "detail_type" + }, + "momkeys": { + "content": { + "value": "lid=2014483720;ppn=383945984;isbn=9789059566071;key=968785;" + }, + "label": "momkeys" + }, + "ovrg_aut": { + "content": [ + { + "value": "Strijbos, Eric", + "code": "7495961" + } + ], + "label": "medewerker" + }, + "medium_srt": { + "content": { + "value": "BOE", + "label": "Boek" + }, + "label": "medium" + }, + "auteur": { + "content": [ + { + "value": "Sullivan, Paul", + "label": "Sullivan, Paul", + "code": "13877950" + } + ], + "label": "auteur" + }, + "bron_naam": { + "content": [ + { + "value": "wise" + } + ], + "label": "bron_naam" + }, + "reeks_serie": { + "content": [ + { + "value": "Wandelgidsen", + "label": "Wandelgidsen", + "code": "34155736" + } + ], + "label": "reeks/serie" + }, + "cwisenr": { + "content": [ + { + "value": "8874552" + } + ], + "label": "cwisenr" + }, + "t1_hoog": { + "content": [ + { + "value": "Wandelgids Berlijn" + } + ], + "label": "t1_hoog" + }, + "materiaal": { + "content": [ + { + "value": "IV" + } + ], + "label": "materiaal" + }, + "titel": { + "content": { + "value": "Wandelgids Berlijn" + }, + "label": "titel" + }, + "id": { + "content": { + "value": "968785" + }, + "label": "id" + }, + "pim": { + "content": [ + { + "value": "18" + } + ], + "label": "pim" + }, + "icon_media": { + "content": { + "value": "book", + "label": "Boek" + }, + "label": "icon_media" + }, + "t1_midden": { + "content": [ + { + "value": "Berlijn" + } + ], + "label": "t1_midden" + }, + "typering": { + "content": [ + { + "value": "2" + } + ], + "label": "typering" + }, + "origin_id": { + "content": [ + { + "value": "968785" + } + ], + "label": "origin_id" + }, + "vestcatgrp": { + "content": [ + { + "value": 0 + } + ], + "label": "vestcatgrp" + }, + "tt_info": { + "content": { + "value": "Gidsje voor de toerist die Berlijn te voet wil ontdekken. Het gidsje bevat geen routebeschrijvingen die de wandelaar via uitgestippelde trajecten langs ..." + }, + "label": "beschrijving" + }, + "siso": { + "content": [ + { + "value": "996.3 Duitsland", + "code": "1765847665" + } + ], + "label": "siso" + }, + "origine": { + "content": { + "value": "wise" + }, + "label": "origine" + }, + "pubjaar": { + "content": { + "label": "2015" + }, + "label": "pubjaar" + }, + "onderwerp": { + "content": [ + { + "value": "Wandeltochten", + "label": "Wandeltochten", + "code": "7808748" + }, + { + "value": "Berlijn", + "label": "Berlijn", + "code": "7798507" + } + ], + "label": "onderwerp" + }, + "detail_uri": { + "content": [ + { + "value": "?sid=414baf2f-729b-4191-a8a7-9919af9b25ef;vestnr=9585;prt=INTERNET;fmt=json;var=portal;event=odetail;backend=wise;oid=968785" + } + ], + "label": "detail_uri" + } + }, + "controls": [ + { + "params": { + "titcode": "968785", + "event": "favadd" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-FAVLIST-ADD", + "type": "mark" + }, + { + "params": { + "titcode": "968785", + "event": "rsrvrqn" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-RESERVE", + "type": "acquire" + } + ], + "editions": [], + "labels": [] + }, + { + "field_display_order": [ + "auteur", + "onderwerp", + "cwisenr", + "tt_info", + "momkeys", + "titel", + "pubjaar", + "reeks_serie", + "typering", + "materiaal", + "pim", + "vestcatgrp", + "ovrg_aut", + "siso", + "icon_media", + "medium_srt", + "t1_hoog", + "bron_naam", + "origine", + "origin_id", + "detail_type", + "detail_uri", + "id" + ], + "version": "2.0", + "backend": "wise", + "availability": [], + "fields": { + "detail_type": { + "content": [ + { + "value": "detail" + } + ], + "label": "detail_type" + }, + "momkeys": { + "content": { + "value": "lid=2019083051;ppn=422213659;isbn=9789044753899;key=1209969;" + }, + "label": "momkeys" + }, + "ovrg_aut": { + "content": [ + { + "value": "Middelbeek, Emmy", + "code": "7403499" + } + ], + "label": "medewerker" + }, + "medium_srt": { + "content": { + "value": "BOE", + "label": "Boek" + }, + "label": "medium" + }, + "auteur": { + "content": [ + { + "value": "Buddée, Gisela", + "label": "Buddée, Gisela", + "code": "16623398" + } + ], + "label": "auteur" + }, + "bron_naam": { + "content": [ + { + "value": "wise" + } + ], + "label": "bron_naam" + }, + "reeks_serie": { + "content": [ + { + "value": "Merian live!", + "label": "Merian live!", + "code": "32729605" + } + ], + "label": "reeks/serie" + }, + "cwisenr": { + "content": [ + { + "value": "10227397" + } + ], + "label": "cwisenr" + }, + "t1_hoog": { + "content": [ + { + "value": "Berlijn" + } + ], + "label": "t1_hoog" + }, + "materiaal": { + "content": [ + { + "value": "IV" + } + ], + "label": "materiaal" + }, + "titel": { + "content": { + "value": "Berlijn" + }, + "label": "titel" + }, + "id": { + "content": { + "value": "1209969" + }, + "label": "id" + }, + "pim": { + "content": [ + { + "value": "18" + } + ], + "label": "pim" + }, + "icon_media": { + "content": { + "value": "book", + "label": "Boek" + }, + "label": "icon_media" + }, + "typering": { + "content": [ + { + "value": "2" + } + ], + "label": "typering" + }, + "origin_id": { + "content": [ + { + "value": "1209969" + } + ], + "label": "origin_id" + }, + "vestcatgrp": { + "content": [ + { + "value": 0 + } + ], + "label": "vestcatgrp" + }, + "tt_info": { + "content": { + "value": "Deeltje uit een kleurrijke serie goedkope reisgidsen voor de stad Berlijn. Voorin worden de bekendste toppers genoemd om te bezoeken of te doen. Daarna ..." + }, + "label": "beschrijving" + }, + "siso": { + "content": [ + { + "value": "996.3 Duitsland", + "code": "1765847665" + } + ], + "label": "siso" + }, + "origine": { + "content": { + "value": "wise" + }, + "label": "origine" + }, + "pubjaar": { + "content": { + "label": "2019" + }, + "label": "pubjaar" + }, + "onderwerp": { + "content": [ + { + "value": "Berlijn", + "label": "Berlijn", + "code": "7798507" + }, + { + "value": "Reisgidsen", + "label": "Reisgidsen", + "code": "7797390" + } + ], + "label": "onderwerp" + }, + "detail_uri": { + "content": [ + { + "value": "?sid=414baf2f-729b-4191-a8a7-9919af9b25ef;vestnr=9585;prt=INTERNET;fmt=json;var=portal;event=odetail;backend=wise;oid=1209969" + } + ], + "label": "detail_uri" + } + }, + "controls": [ + { + "params": { + "titcode": "1209969", + "event": "favadd" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-FAVLIST-ADD", + "type": "mark" + }, + { + "params": { + "titcode": "1209969", + "event": "rsrvrqn" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-RESERVE", + "type": "acquire" + } + ], + "editions": [], + "labels": [] + }, + { + "field_display_order": [ + "auteur", + "onderwerp", + "cwisenr", + "tt_info", + "momkeys", + "titel", + "pubjaar", + "reeks_serie", + "typering", + "materiaal", + "pim", + "vestcatgrp", + "ovrg_aut", + "siso", + "icon_media", + "medium_srt", + "t1_hoog", + "bron_naam", + "origine", + "origin_id", + "detail_type", + "detail_uri", + "id" + ], + "version": "2.0", + "backend": "wise", + "availability": [], + "fields": { + "detail_type": { + "content": [ + { + "value": "detail" + } + ], + "label": "detail_type" + }, + "momkeys": { + "content": { + "value": "lid=2017472571;ppn=413571750;isbn=9789021568225;key=1172079;" + }, + "label": "momkeys" + }, + "ovrg_aut": { + "content": [ + { + "value": "Adenis, Pierre", + "code": "33986427" + }, + { + "value": "Reusink, Frans", + "code": "12130438" + } + ], + "label": "medewerker" + }, + "medium_srt": { + "content": { + "value": "BOE", + "label": "Boek" + }, + "label": "medium" + }, + "auteur": { + "content": [ + { + "value": "Simonis, Damien", + "label": "Simonis, Damien", + "code": "10786265" + } + ], + "label": "auteur" + }, + "bron_naam": { + "content": [ + { + "value": "wise" + } + ], + "label": "bron_naam" + }, + "reeks_serie": { + "content": [ + { + "value": "National Geographic reisgids", + "label": "National Geographic reisgids", + "code": "26199954" + } + ], + "label": "reeks/serie" + }, + "cwisenr": { + "content": [ + { + "value": "10026285" + } + ], + "label": "cwisenr" + }, + "t1_hoog": { + "content": [ + { + "value": "Berlijn" + } + ], + "label": "t1_hoog" + }, + "materiaal": { + "content": [ + { + "value": "IV" + } + ], + "label": "materiaal" + }, + "titel": { + "content": { + "value": "Berlijn" + }, + "label": "titel" + }, + "id": { + "content": { + "value": "1172079" + }, + "label": "id" + }, + "pim": { + "content": [ + { + "value": "18" + } + ], + "label": "pim" + }, + "icon_media": { + "content": { + "value": "book", + "label": "Boek" + }, + "label": "icon_media" + }, + "typering": { + "content": [ + { + "value": "2" + } + ], + "label": "typering" + }, + "origin_id": { + "content": [ + { + "value": "1172079" + } + ], + "label": "origin_id" + }, + "vestcatgrp": { + "content": [ + { + "value": 0 + } + ], + "label": "vestcatgrp" + }, + "tt_info": { + "content": { + "value": "Deze mooi uitgevoerde reisgids over Berlijn biedt vooral veel informatie over de cultuur en geschiedenis van deze stad. Na een algemene cultuurhistorische ..." + }, + "label": "beschrijving" + }, + "siso": { + "content": [ + { + "value": "996.3 Duitsland", + "code": "1765847665" + } + ], + "label": "siso" + }, + "origine": { + "content": { + "value": "wise" + }, + "label": "origine" + }, + "pubjaar": { + "content": { + "label": "2018" + }, + "label": "pubjaar" + }, + "onderwerp": { + "content": [ + { + "value": "Berlijn", + "label": "Berlijn", + "code": "7798507" + }, + { + "value": "Reisgidsen", + "label": "Reisgidsen", + "code": "7797390" + } + ], + "label": "onderwerp" + }, + "detail_uri": { + "content": [ + { + "value": "?sid=414baf2f-729b-4191-a8a7-9919af9b25ef;vestnr=9585;prt=INTERNET;fmt=json;var=portal;event=odetail;backend=wise;oid=1172079" + } + ], + "label": "detail_uri" + } + }, + "controls": [ + { + "params": { + "titcode": "1172079", + "event": "favadd" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-FAVLIST-ADD", + "type": "mark" + }, + { + "params": { + "titcode": "1172079", + "event": "rsrvrqn" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-RESERVE", + "type": "acquire" + } + ], + "editions": [], + "labels": [] + }, + { + "field_display_order": [ + "auteur", + "onderwerp", + "cwisenr", + "tt_info", + "momkeys", + "titel", + "pubjaar", + "reeks_serie", + "typering", + "materiaal", + "pim", + "vestcatgrp", + "ovrg_aut", + "siso", + "icon_media", + "medium_srt", + "t1_hoog", + "bron_naam", + "origine", + "origin_id", + "detail_type", + "detail_uri", + "id" + ], + "version": "2.0", + "backend": "wise", + "availability": [], + "fields": { + "detail_type": { + "content": [ + { + "value": "detail" + } + ], + "label": "detail_type" + }, + "momkeys": { + "content": { + "value": "lid=2017042721;ppn=408698055;isbn=9783829756310;key=1087319;" + }, + "label": "momkeys" + }, + "ovrg_aut": { + "content": [ + { + "value": "Gussen, Michiel", + "code": "18518701" + }, + { + "value": "Harmans, Gerard M.L.", + "code": "7354444" + } + ], + "label": "medewerker" + }, + "medium_srt": { + "content": { + "value": "BOE", + "label": "Boek" + }, + "label": "medium" + }, + "auteur": { + "content": [ + { + "value": "Berger, Christine", + "label": "Berger, Christine", + "code": "24439354" + } + ], + "label": "auteur" + }, + "bron_naam": { + "content": [ + { + "value": "wise" + } + ], + "label": "bron_naam" + }, + "reeks_serie": { + "content": [ + { + "value": "Marco Polo", + "label": "Marco Polo", + "code": "33118191" + } + ], + "label": "reeks/serie" + }, + "cwisenr": { + "content": [ + { + "value": "9733492" + } + ], + "label": "cwisenr" + }, + "t1_hoog": { + "content": [ + { + "value": "Berlijn" + } + ], + "label": "t1_hoog" + }, + "materiaal": { + "content": [ + { + "value": "IV" + } + ], + "label": "materiaal" + }, + "titel": { + "content": { + "value": "Berlijn" + }, + "label": "titel" + }, + "id": { + "content": { + "value": "1087319" + }, + "label": "id" + }, + "pim": { + "content": [ + { + "value": "18" + } + ], + "label": "pim" + }, + "icon_media": { + "content": { + "value": "book", + "label": "Boek" + }, + "label": "icon_media" + }, + "typering": { + "content": [ + { + "value": "2" + } + ], + "label": "typering" + }, + "origin_id": { + "content": [ + { + "value": "1087319" + } + ], + "label": "origin_id" + }, + "vestcatgrp": { + "content": [ + { + "value": 0 + } + ], + "label": "vestcatgrp" + }, + "tt_info": { + "content": { + "value": "De bekende Marco-Polo reisgidsen zijn in 2012 in een nieuw jasje gestoken. De compacte gidsjes, gewijd aan de meest populaire toeristische bestemmingen, zijn ..." + }, + "label": "beschrijving" + }, + "siso": { + "content": [ + { + "value": "996.3 Duitsland", + "code": "1765847665" + } + ], + "label": "siso" + }, + "origine": { + "content": { + "value": "wise" + }, + "label": "origine" + }, + "pubjaar": { + "content": { + "label": "2017" + }, + "label": "pubjaar" + }, + "onderwerp": { + "content": [ + { + "value": "Berlijn", + "label": "Berlijn", + "code": "7798507" + }, + { + "value": "Reisgidsen", + "label": "Reisgidsen", + "code": "7797390" + } + ], + "label": "onderwerp" + }, + "detail_uri": { + "content": [ + { + "value": "?sid=414baf2f-729b-4191-a8a7-9919af9b25ef;vestnr=9585;prt=INTERNET;fmt=json;var=portal;event=odetail;backend=wise;oid=1087319" + } + ], + "label": "detail_uri" + } + }, + "controls": [ + { + "params": { + "titcode": "1087319", + "event": "favadd" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-FAVLIST-ADD", + "type": "mark" + }, + { + "params": { + "titcode": "1087319", + "event": "rsrvrqn" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-RESERVE", + "type": "acquire" + } + ], + "editions": [], + "labels": [] + }, + { + "field_display_order": [ + "onderwerp", + "cwisenr", + "tt_info", + "momkeys", + "titel", + "pubjaar", + "reeks_serie", + "typering", + "materiaal", + "pim", + "vestcatgrp", + "ovrg_aut", + "siso", + "icon_media", + "medium_srt", + "t1_hoog", + "t1_midden", + "bron_naam", + "origine", + "origin_id", + "detail_type", + "detail_uri", + "id" + ], + "version": "2.0", + "backend": "wise", + "availability": [], + "fields": { + "detail_type": { + "content": [ + { + "value": "detail" + } + ], + "label": "detail_type" + }, + "momkeys": { + "content": { + "value": "lid=2014494945;ppn=396059899;isbn=9789401423830;key=992393;" + }, + "label": "momkeys" + }, + "ovrg_aut": { + "content": [ + { + "value": "Maes, Valérie", + "code": "30369326" + }, + { + "value": "Georgen, Annabelle", + "code": "39605984" + }, + { + "value": "Delouvy, Isabelle", + "code": "39249390" + } + ], + "label": "medewerker" + }, + "medium_srt": { + "content": { + "value": "BOE", + "label": "Boek" + }, + "label": "medium" + }, + "bron_naam": { + "content": [ + { + "value": "wise" + } + ], + "label": "bron_naam" + }, + "reeks_serie": { + "content": [ + { + "value": "Groene gids weekend", + "label": "Groene gids weekend", + "code": "32649055" + } + ], + "label": "reeks/serie" + }, + "cwisenr": { + "content": [ + { + "value": "8948865" + } + ], + "label": "cwisenr" + }, + "t1_hoog": { + "content": [ + { + "value": "Berlijn" + } + ], + "label": "t1_hoog" + }, + "materiaal": { + "content": [ + { + "value": "IV" + } + ], + "label": "materiaal" + }, + "titel": { + "content": { + "value": "Berlijn" + }, + "label": "titel" + }, + "id": { + "content": { + "value": "992393" + }, + "label": "id" + }, + "pim": { + "content": [ + { + "value": "18" + } + ], + "label": "pim" + }, + "icon_media": { + "content": { + "value": "book", + "label": "Boek" + }, + "label": "icon_media" + }, + "t1_midden": { + "content": [ + { + "value": "De groene reisgids weekend Berlijn" + }, + { + "value": "Weekend Berlijn" + } + ], + "label": "t1_midden" + }, + "typering": { + "content": [ + { + "value": "2" + } + ], + "label": "typering" + }, + "origin_id": { + "content": [ + { + "value": "992393" + } + ], + "label": "origin_id" + }, + "vestcatgrp": { + "content": [ + { + "value": 0 + } + ], + "label": "vestcatgrp" + }, + "tt_info": { + "content": { + "value": "De reisgidsen uit de reeks 'Groene Reisgids weekend' sluiten qua opzet en vormgeving aan bij de klassieke 'Groene Gidsen' van Michelin, maar focussen op ..." + }, + "label": "beschrijving" + }, + "siso": { + "content": [ + { + "value": "996.3 Duitsland", + "code": "1765847665" + } + ], + "label": "siso" + }, + "origine": { + "content": { + "value": "wise" + }, + "label": "origine" + }, + "pubjaar": { + "content": { + "label": "2015" + }, + "label": "pubjaar" + }, + "onderwerp": { + "content": [ + { + "value": "Berlijn", + "label": "Berlijn", + "code": "7798507" + }, + { + "value": "Reisgidsen", + "label": "Reisgidsen", + "code": "7797390" + } + ], + "label": "onderwerp" + }, + "detail_uri": { + "content": [ + { + "value": "?sid=414baf2f-729b-4191-a8a7-9919af9b25ef;vestnr=9585;prt=INTERNET;fmt=json;var=portal;event=odetail;backend=wise;oid=992393" + } + ], + "label": "detail_uri" + } + }, + "controls": [ + { + "params": { + "titcode": "992393", + "event": "favadd" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-FAVLIST-ADD", + "type": "mark" + }, + { + "params": { + "titcode": "992393", + "event": "rsrvrqn" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-RESERVE", + "type": "acquire" + } + ], + "editions": [], + "labels": [] + }, + { + "field_display_order": [ + "auteur", + "onderwerp", + "cwisenr", + "tt_info", + "momkeys", + "titel", + "pubjaar", + "reeks_serie", + "typering", + "materiaal", + "pim", + "vestcatgrp", + "ovrg_aut", + "siso", + "icon_media", + "medium_srt", + "t1_hoog", + "bron_naam", + "origine", + "origin_id", + "detail_type", + "detail_uri", + "id" + ], + "version": "2.0", + "backend": "wise", + "availability": [], + "fields": { + "detail_type": { + "content": [ + { + "value": "detail" + } + ], + "label": "detail_type" + }, + "momkeys": { + "content": { + "value": "lid=2014461967;ppn=395479916;isbn=9789401423151;key=992394;" + }, + "label": "momkeys" + }, + "ovrg_aut": { + "content": [ + { + "value": "Peeters, Mireille", + "code": "32052102" + }, + { + "value": "Page, Olivier", + "code": "36437129" + } + ], + "label": "medewerker" + }, + "medium_srt": { + "content": { + "value": "BOE", + "label": "Boek" + }, + "label": "medium" + }, + "auteur": { + "content": [ + { + "value": "Gloaguen, Philippe", + "label": "Gloaguen, Philippe", + "code": "7183906" + } + ], + "label": "auteur" + }, + "bron_naam": { + "content": [ + { + "value": "wise" + } + ], + "label": "bron_naam" + }, + "reeks_serie": { + "content": [ + { + "value": "Trotter", + "label": "Trotter", + "code": "33980042" + } + ], + "label": "reeks/serie" + }, + "cwisenr": { + "content": [ + { + "value": "8948866" + } + ], + "label": "cwisenr" + }, + "t1_hoog": { + "content": [ + { + "value": "Berlijn" + } + ], + "label": "t1_hoog" + }, + "materiaal": { + "content": [ + { + "value": "IV" + } + ], + "label": "materiaal" + }, + "titel": { + "content": { + "value": "Berlijn" + }, + "label": "titel" + }, + "id": { + "content": { + "value": "992394" + }, + "label": "id" + }, + "pim": { + "content": [ + { + "value": "18" + } + ], + "label": "pim" + }, + "icon_media": { + "content": { + "value": "book", + "label": "Boek" + }, + "label": "icon_media" + }, + "typering": { + "content": [ + { + "value": "2" + } + ], + "label": "typering" + }, + "origin_id": { + "content": [ + { + "value": "992394" + } + ], + "label": "origin_id" + }, + "vestcatgrp": { + "content": [ + { + "value": 0 + } + ], + "label": "vestcatgrp" + }, + "tt_info": { + "content": { + "value": "Deze 'Trotter'-reisgids over Berlijn wil vooral basisinformatie bieden en is dan ook sober uitgevoerd in tweekleurendruk zonder foto's. Na beknopte ..." + }, + "label": "beschrijving" + }, + "siso": { + "content": [ + { + "value": "996.3 Duitsland", + "code": "1765847665" + } + ], + "label": "siso" + }, + "origine": { + "content": { + "value": "wise" + }, + "label": "origine" + }, + "pubjaar": { + "content": { + "label": "2015" + }, + "label": "pubjaar" + }, + "onderwerp": { + "content": [ + { + "value": "Berlijn", + "label": "Berlijn", + "code": "7798507" + }, + { + "value": "Reisgidsen", + "label": "Reisgidsen", + "code": "7797390" + } + ], + "label": "onderwerp" + }, + "detail_uri": { + "content": [ + { + "value": "?sid=414baf2f-729b-4191-a8a7-9919af9b25ef;vestnr=9585;prt=INTERNET;fmt=json;var=portal;event=odetail;backend=wise;oid=992394" + } + ], + "label": "detail_uri" + } + }, + "controls": [ + { + "params": { + "titcode": "992394", + "event": "favadd" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-FAVLIST-ADD", + "type": "mark" + }, + { + "params": { + "titcode": "992394", + "event": "rsrvrqn" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-RESERVE", + "type": "acquire" + } + ], + "editions": [], + "labels": [] + }, + { + "field_display_order": [ + "auteur", + "onderwerp", + "cwisenr", + "tt_info", + "momkeys", + "titel", + "pubjaar", + "reeks_serie", + "typering", + "materiaal", + "pim", + "vestcatgrp", + "ovrg_aut", + "siso", + "icon_media", + "medium_srt", + "t1_hoog", + "bron_naam", + "origine", + "origin_id", + "detail_type", + "detail_uri", + "id" + ], + "version": "2.0", + "backend": "wise", + "availability": [], + "fields": { + "detail_type": { + "content": [ + { + "value": "detail" + } + ], + "label": "detail_type" + }, + "momkeys": { + "content": { + "value": "lid=2015121485;ppn=39159611X;isbn=9789021559544;key=995042;" + }, + "label": "momkeys" + }, + "ovrg_aut": { + "content": [ + { + "value": "Adenis, Pierre", + "code": "33986427" + }, + { + "value": "Reusink, Frans", + "code": "12130438" + } + ], + "label": "medewerker" + }, + "medium_srt": { + "content": { + "value": "BOE", + "label": "Boek" + }, + "label": "medium" + }, + "auteur": { + "content": [ + { + "value": "Simonis, Damien", + "label": "Simonis, Damien", + "code": "10786265" + } + ], + "label": "auteur" + }, + "bron_naam": { + "content": [ + { + "value": "wise" + } + ], + "label": "bron_naam" + }, + "reeks_serie": { + "content": [ + { + "value": "National Geographic reisgids", + "label": "National Geographic reisgids", + "code": "26199954" + } + ], + "label": "reeks/serie" + }, + "cwisenr": { + "content": [ + { + "value": "8960746" + } + ], + "label": "cwisenr" + }, + "t1_hoog": { + "content": [ + { + "value": "Berlijn" + } + ], + "label": "t1_hoog" + }, + "materiaal": { + "content": [ + { + "value": "IV" + } + ], + "label": "materiaal" + }, + "titel": { + "content": { + "value": "Berlijn" + }, + "label": "titel" + }, + "id": { + "content": { + "value": "995042" + }, + "label": "id" + }, + "pim": { + "content": [ + { + "value": "18" + } + ], + "label": "pim" + }, + "icon_media": { + "content": { + "value": "book", + "label": "Boek" + }, + "label": "icon_media" + }, + "typering": { + "content": [ + { + "value": "2" + } + ], + "label": "typering" + }, + "origin_id": { + "content": [ + { + "value": "995042" + } + ], + "label": "origin_id" + }, + "vestcatgrp": { + "content": [ + { + "value": 0 + } + ], + "label": "vestcatgrp" + }, + "tt_info": { + "content": { + "value": "Deze mooi uitgevoerde reisgids over Berlijn biedt vooral veel informatie over de cultuur en geschiedenis van deze stad. Na een algemene cultuurhistorische ..." + }, + "label": "beschrijving" + }, + "siso": { + "content": [ + { + "value": "996.3 Duitsland", + "code": "1765847665" + } + ], + "label": "siso" + }, + "origine": { + "content": { + "value": "wise" + }, + "label": "origine" + }, + "pubjaar": { + "content": { + "label": "2015" + }, + "label": "pubjaar" + }, + "onderwerp": { + "content": [ + { + "value": "Berlijn", + "label": "Berlijn", + "code": "7798507" + }, + { + "value": "Reisgidsen", + "label": "Reisgidsen", + "code": "7797390" + } + ], + "label": "onderwerp" + }, + "detail_uri": { + "content": [ + { + "value": "?sid=414baf2f-729b-4191-a8a7-9919af9b25ef;vestnr=9585;prt=INTERNET;fmt=json;var=portal;event=odetail;backend=wise;oid=995042" + } + ], + "label": "detail_uri" + } + }, + "controls": [ + { + "params": { + "titcode": "995042", + "event": "favadd" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-FAVLIST-ADD", + "type": "mark" + }, + { + "params": { + "titcode": "995042", + "event": "rsrvrqn" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-RESERVE", + "type": "acquire" + } + ], + "editions": [], + "labels": [] + }, + { + "field_display_order": [ + "auteur", + "onderwerp", + "cwisenr", + "tt_info", + "momkeys", + "titel", + "pubjaar", + "typering", + "materiaal", + "pim", + "vestcatgrp", + "ovrg_aut", + "siso", + "icon_media", + "medium_srt", + "t1_hoog", + "bron_naam", + "origine", + "origin_id", + "detail_type", + "detail_uri", + "id" + ], + "version": "2.0", + "backend": "wise", + "availability": [], + "fields": { + "detail_type": { + "content": [ + { + "value": "detail" + } + ], + "label": "detail_type" + }, + "momkeys": { + "content": { + "value": "lid=2014293578;ppn=377415014;isbn=9789023486183;key=927920;" + }, + "label": "momkeys" + }, + "ovrg_aut": { + "content": [ + { + "value": "Sassen, Simone", + "code": "25227076" + } + ], + "label": "medewerker" + }, + "medium_srt": { + "content": { + "value": "BOE", + "label": "Boek" + }, + "label": "medium" + }, + "auteur": { + "content": [ + { + "value": "Nooteboom, Cees", + "label": "Nooteboom, Cees", + "code": "6874395" + } + ], + "label": "auteur" + }, + "bron_naam": { + "content": [ + { + "value": "wise" + } + ], + "label": "bron_naam" + }, + "cwisenr": { + "content": [ + { + "value": "8673785" + } + ], + "label": "cwisenr" + }, + "t1_hoog": { + "content": [ + { + "value": "Berlijn" + } + ], + "label": "t1_hoog" + }, + "materiaal": { + "content": [ + { + "value": "IV" + } + ], + "label": "materiaal" + }, + "titel": { + "content": { + "value": "Berlijn" + }, + "label": "titel" + }, + "id": { + "content": { + "value": "927920" + }, + "label": "id" + }, + "pim": { + "content": [ + { + "value": "18" + } + ], + "label": "pim" + }, + "icon_media": { + "content": { + "value": "book", + "label": "Boek" + }, + "label": "icon_media" + }, + "typering": { + "content": [ + { + "value": "2" + } + ], + "label": "typering" + }, + "origin_id": { + "content": [ + { + "value": "927920" + } + ], + "label": "origin_id" + }, + "vestcatgrp": { + "content": [ + { + "value": 0 + } + ], + "label": "vestcatgrp" + }, + "tt_info": { + "content": { + "value": "Impressies van Berlijn in 1989, 1999 en 2009." + }, + "label": "beschrijving" + }, + "siso": { + "content": [ + { + "value": "996 Duitsland", + "code": "1765893516" + } + ], + "label": "siso" + }, + "origine": { + "content": { + "value": "wise" + }, + "label": "origine" + }, + "pubjaar": { + "content": { + "label": "2014" + }, + "label": "pubjaar" + }, + "onderwerp": { + "content": [ + { + "value": "Berlijn", + "label": "Berlijn", + "code": "7798507" + }, + { + "value": "Verhalen", + "label": "Verhalen", + "code": "7797302" + } + ], + "label": "onderwerp" + }, + "detail_uri": { + "content": [ + { + "value": "?sid=414baf2f-729b-4191-a8a7-9919af9b25ef;vestnr=9585;prt=INTERNET;fmt=json;var=portal;event=odetail;backend=wise;oid=927920" + } + ], + "label": "detail_uri" + } + }, + "controls": [ + { + "params": { + "titcode": "927920", + "event": "favadd" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-FAVLIST-ADD", + "type": "mark" + }, + { + "params": { + "titcode": "927920", + "event": "rsrvrqn" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-RESERVE", + "type": "acquire" + } + ], + "editions": [], + "labels": [] + }, + { + "field_display_order": [ + "auteur", + "onderwerp", + "cwisenr", + "tt_info", + "momkeys", + "titel", + "pubjaar", + "reeks_serie", + "typering", + "materiaal", + "pim", + "vestcatgrp", + "ovrg_aut", + "siso", + "icon_media", + "medium_srt", + "t1_hoog", + "bron_naam", + "origine", + "origin_id", + "detail_type", + "detail_uri", + "id" + ], + "version": "2.0", + "backend": "wise", + "availability": [], + "fields": { + "detail_type": { + "content": [ + { + "value": "detail" + } + ], + "label": "detail_type" + }, + "momkeys": { + "content": { + "value": "lid=2002280325;ppn=197286577;isbn=9789054953272;key=166736;" + }, + "label": "momkeys" + }, + "ovrg_aut": { + "content": [ + { + "value": "Bakker, Piet de", + "code": "12367811" + } + ], + "label": "medewerker" + }, + "medium_srt": { + "content": { + "value": "BOE", + "label": "Boek" + }, + "label": "medium" + }, + "auteur": { + "content": [ + { + "value": "Hatt, Christine", + "label": "Hatt, Christine", + "code": "16577748" + } + ], + "label": "auteur" + }, + "bron_naam": { + "content": [ + { + "value": "wise" + } + ], + "label": "bron_naam" + }, + "reeks_serie": { + "content": [ + { + "value": "Wereldsteden", + "label": "Wereldsteden", + "code": "1767616613" + } + ], + "label": "reeks/serie" + }, + "cwisenr": { + "content": [ + { + "value": "864680" + } + ], + "label": "cwisenr" + }, + "t1_hoog": { + "content": [ + { + "value": "Berlijn" + }, + { + "value": "Berlin" + } + ], + "label": "t1_hoog" + }, + "materiaal": { + "content": [ + { + "value": "I" + }, + { + "value": "I" + } + ], + "label": "materiaal" + }, + "titel": { + "content": { + "value": "Berlijn" + }, + "label": "titel" + }, + "id": { + "content": { + "value": "166736" + }, + "label": "id" + }, + "pim": { + "content": [ + { + "value": "18" + } + ], + "label": "pim" + }, + "icon_media": { + "content": { + "value": "book", + "label": "Boek" + }, + "label": "icon_media" + }, + "typering": { + "content": [ + { + "value": "5" + } + ], + "label": "typering" + }, + "origin_id": { + "content": [ + { + "value": "166736" + } + ], + "label": "origin_id" + }, + "vestcatgrp": { + "content": [ + { + "value": 0 + } + ], + "label": "vestcatgrp" + }, + "tt_info": { + "content": { + "value": "Naast de geschiedenis van Berlijn wordt ondermeer aandacht besteed aan architectuur, huisvesting, onderwijs, musea, misdaad, geloof en industrie. Met vele ..." + }, + "label": "beschrijving" + }, + "siso": { + "content": [ + { + "value": "996.2 Duitsland", + "code": "1765847503" + } + ], + "label": "siso" + }, + "origine": { + "content": { + "value": "wise" + }, + "label": "origine" + }, + "pubjaar": { + "content": { + "label": "2002" + }, + "label": "pubjaar" + }, + "onderwerp": { + "content": [ + { + "value": "Duitsland", + "label": "Duitsland" + }, + { + "value": "Steden", + "label": "Steden" + }, + { + "value": "20e eeuw", + "label": "20e eeuw" + }, + { + "value": "Bouwkunst", + "label": "Bouwkunst" + }, + { + "value": "Parken en plantsoenen", + "label": "Parken en plantsoenen" + }, + { + "value": "Woningbouw", + "label": "Woningbouw" + }, + { + "value": "Onderwijs", + "label": "Onderwijs" + }, + { + "value": "Geloof en filosofie", + "label": "Geloof en filosofie" + }, + { + "value": "Handel", + "label": "Handel" + }, + { + "value": "Industrieën", + "label": "Industrieën" + }, + { + "value": "Misdaden", + "label": "Misdaden" + }, + { + "value": "Verkeer en vervoer", + "label": "Verkeer en vervoer" + }, + { + "value": "Winkels", + "label": "Winkels" + }, + { + "value": "Voedsel", + "label": "Voedsel" + }, + { + "value": "Hobby's en vrije tijd", + "label": "Hobby's en vrije tijd" + }, + { + "value": "Museum", + "label": "Museum" + }, + { + "value": "Feesten", + "label": "Feesten" + }, + { + "value": "Beroemdheden", + "label": "Beroemdheden" + }, + { + "value": "Vroeger", + "label": "Vroeger" + }, + { + "value": "Berlijn", + "label": "Berlijn", + "code": "7798507" + } + ], + "label": "onderwerp" + }, + "detail_uri": { + "content": [ + { + "value": "?sid=414baf2f-729b-4191-a8a7-9919af9b25ef;vestnr=9585;prt=INTERNET;fmt=json;var=portal;event=odetail;backend=wise;oid=166736" + } + ], + "label": "detail_uri" + } + }, + "controls": [ + { + "params": { + "titcode": "166736", + "event": "favadd" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-FAVLIST-ADD", + "type": "mark" + }, + { + "params": { + "titcode": "166736", + "event": "rsrvrqn" + }, + "label": "WCP-BACKEND__TITLE-CONTROL-RESERVE", + "type": "acquire" + } + ], + "editions": [], + "labels": [] + } + ], + "error": "", + "uris": { + "base": "?sid=414baf2f-729b-4191-a8a7-9919af9b25ef;catalog=default;backend=wise;var=portal;vcgrpt=0\r\n ;offset=0;fmt=json;preset=all;sortkey=relevantie;sortorder=desc;event=osearch;vcgrpf=0;search_in=iets;qs=berlijn;amount=10;prt=INTERNET;vestnr=9585;" + }, + "id": "" +} \ No newline at end of file diff --git a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/networking/AndroidHttpClientFactory.java b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/networking/AndroidHttpClientFactory.java index 7660d93c6..694b9cc75 100644 --- a/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/networking/AndroidHttpClientFactory.java +++ b/opacclient/opacapp/src/main/java/de/geeksfactory/opacclient/networking/AndroidHttpClientFactory.java @@ -62,7 +62,7 @@ public OkHttpClient getNewOkHttpClient(boolean customssl, boolean tls_only, boolean allCipherSuites) { OkHttpClient.Builder client = super.getOkHttpClientBuilder(customssl, tls_only, allCipherSuites, - Build.VERSION.SDK_INT == 24); + Build.VERSION.SDK_INT == 24, null); int cacheSize = 50 * 1024 * 1024; // 50MB client.cache(new Cache(OpacClient.context.getCacheDir(), cacheSize)); return DebugTools.prepareHttpClient(client).build(); diff --git a/opacclient/opacapp/src/main/res/values-de/strings.xml b/opacclient/opacapp/src/main/res/values-de/strings.xml index b45c663cb..66cec4f45 100644 --- a/opacclient/opacapp/src/main/res/values-de/strings.xml +++ b/opacclient/opacapp/src/main/res/values-de/strings.xml @@ -351,4 +351,5 @@ Verlängerbare fällige Medien werden verlängert… Es gibt keine verlängerbaren fälligen Medien. Ein anonymes Konto wurde für dich angelegt. + Suchbereich diff --git a/opacclient/opacapp/src/main/res/values-nl/strings.xml b/opacclient/opacapp/src/main/res/values-nl/strings.xml new file mode 100644 index 000000000..5cbb939ac --- /dev/null +++ b/opacclient/opacapp/src/main/res/values-nl/strings.xml @@ -0,0 +1,358 @@ + + + Web Opac + Web Opac + Web Opac + Vestiging + Barcodes + Zoeken starten + Instellingen + Account + Over + Over deze app + Changelog + Sluiten + Licentiekennisgevingen + Medeauteurs en dankzeggingen + Ontwikkelaarsinstellingen + Details + Exemplaren + Inleverdatum + Gereserveerd + Naar collectie + Reserveer + Leen e-book + Reservering uitvoeren… + S.V.P. voeg e-mail adres toe aan de instellingen. + Lenen uitvoeren… + Je hebt geen logingegevens gespecifieerd voor dit account in de instellingen. + Uitstaande boetes: + Account geldig tot: + Alle informatie wordt verstrekt zonder aansprakelijkheid. + Geleend + Reserveringen + Niets geleend + Niets gereserveerd + Reservering echt annuleren? + Item echt verlengen? + Ja + Nee + Annuleer + Verwijder + OK + Reservering wordt geannuleerd… + Verlenging wordt doorgevoerd… + Download information is being retrieved… + To read the e-book, you need a separate app, for example \'Aldiko\'. Click \'Ignore\' if you already have such an app, this message won\'t show up again in this case. Click \'Download\' to open up the Play Store to download Aldiko. + To open this medium, you need a separate app, for example OverDrive\'s own app. Click \'Ignore\' if you already have such an app, this message won\'t show up again in this case. Click \'Download\' to open up the Play Store to download the OverDrive app. + Ignore + All verlengbare items worden verlengd… + Alle items velengen? Er kunnen kosten mee verbonden zijn. + Web Opac foutbericht: + Welkom! + Om te beginnen dien je een bibliotheek te selecteren. + Dit account kan anoniem zijn (alleen zoeken), of een bibliotheekkaartnummer en wachtwoord bevatten ( accountfuncties ingeschakeld). Extra accounts kunnen later toegevoegd worden. + Bibliotheek selecteren + Rapport verzenden + Verzend rapport… + Rapport verzonden. Dank je! + Fout rapport kon niet worden verzonden. + Meldingen + Verlopen items + Melding, indien een item teruggebracht dient te worden (geen garantie) + Alleen controleren met WiFi + Geen informatie downloaden over mobiele netwerken. Meldingen kunnen hierdoor gemist worden. + Terugbreng meldingen + + dezelfde dag + 1 dag van tevoren + 3 dagen van tevoren + 1 week van tevoren + + Start scherm + Welk scherm dient getoond te worden bij opstarten? + + Zoeken + Account + Favorieten + Informatie + + + Zoeken + account + starred + info + + Waarschuwingstijdstip + Hoe lang voor de inleverdatum dient er gewaarschuwd te worden? + + %d item moet ingeleverd of verlengd worden! + %d items moeten ingeleverd of verlengd worden! + + Items dienen ingeleverd te worden + + %d item is verlopen! + %d items zijn verlopen! + + Items zijn te laat ingeleverd + +%d meer + Later + Niet weer + Volumes + Volumes tonen + Toevoegen aan favorieten + Het item is toegevoegd aan je favorieten. + Even wachten, totdat de details geladen zijn. + Dit item kan niet toegevoegd worden aan je lijst. + Dit is je favorietenlijst. Je kan items toevoegen door op de ster te drukken in de detail pagina. Voor elke toegevoegde bibliotheek wordt een aparte lijst bijgehouden. + Delen + Even wachten, totdat de details geladen zijn. + Door deze bibliotheek niet ondersteund. + Niet ondersteund + This feature is not yet supported in your library. Sorry \uD83D\uDE1E +
If you have experience in programming and some spare time, you might be able to help us to implement it. You can find more information about this on GitHub]]>.
+ E-mail schrijven + Kan geen aanvullende informatie voor deze bibliotheek laden. + We hebben geen informatie over deze bibliotheek om weer te geven. + De geselecteerde lijst komt uit een andere bibliotheek! Probeer over te schakelen naar de juiste bibliotheek + Import kompleet. + De verbinding met de bibliotheekserver is mislukt. Controleer uw internetverbinding. Als het probleem aanhoudt, is er mogelijk een probleem met de bibliotheekserver of kon de app de response van de server niet verwerken. + De verbinding met de bibliotheekserver is mislukt. Controleer uw internetverbinding. Als het probleem zich blijft voordoen, is er mogelijk een probleem met de bibliotheekserver. + Opnieuw proberen + De beveiligde verbinding met de bibliotheekserver is mislukt. Probeer het alstublieft opnieuw. Als het probleem aanhoudt, is er mogelijk iemand die uw verbinding onderschept. Neem contact op met https://opac.app/en/support/ als het probleem zich blijft voordoen in meerdere wifi-netwerken. + Account zonder naam + Accounts + Account toevoegen + Accounts + Account wijzigen + Bibliotheken en lenergegevens beheren + Account type + Label + optioneel, alleen voor het identificeren van het account in deze app. + Pas nummer/gebruikersnaam + Wachtwoord + Bibliotheek + Account echt verwijderen? + Account selecteren + Privacybeleid + Bibliotheek + Zoeken + Account + Favorieten + Informatie + Overige + Instellingen + Over deze app + Accountkeuze + Er is een fout opgetreden. Een ogenblikje a.u.b. + Web Opac App: Er is een fout opgetreden. + Druk hier om een foutrapport op te sturen. + Web Opac App is gecrasht + Er is een fout opgetreden in de Opac App! Stuur het foutenrapport via e-mail zodat we dit kunnen oplossen. + Verversen + Allen verlengen + Wacht tot de weergave is vernieuwd. + Bevestigen + Bevestigen + De getoonde gegevens zijn up-to-date. + + De getoonde gegevens zijn 1 minuut oud. + De getoonde gegevens zijn %d minuten oud. + + + De getoonde gegevens zijn 1 uur oud. + De getoonde gegevens zijn %d uren oud. + + + De getoonde gegevens zijn 1 dag oud. + De getoonde gegevens zijn %d dagen oud. + + Uitgebreid zoeken + Vrij zoeken + Barcode scanner installeren? + Deze functie vereist de installatie van een barcodescanner-applicatie. Wilt u er een downloaden? + Google Play + Amazon + + 1 zoekresultaat + %d zoekresultaten + + Delen + Export + Import + Als tekst delen + Er is een fout opgetreden tijdens het exporteren. Probeer het later nog eens. + Er is een fout opgetreden tijdens het importeren. + Importbestanden dienen in het .json formaat te zijn. + Om een ​​bestand te selecteren om te importeren, moet u een compatibele bestandsverkenner-app installeren. + Bibliotheken in de buurt vinden + Locatie wordt opgezocht… + Locatie is niet beschikbaar op dit apparaat. Mogelijk moet je dit inschakelen in de instellingen. + Volledige lijst tonen + NFC zoeken + Experimenteel. Alleen op sommige apparaten en in sommige bibliotheken. + Notificaties werkt op dit moment niet. + De zoekopdracht heeft geen resultaten opgeleverd. + Deze bibliotheek heeft nu een eigen app met uitgebreide functies. We raden aan om deze speciale app te gebruiken. + Downloaden + E-mail adres + Vereist voor e-bookreserveringen + Wisselen van accounts is mislukt. Start een nieuwe zoekopdracht. + Resultaat delen + Link delen + Details exporteren + Deze bibliotheek ondersteunt geen beveiligde HTTPS-verbinding. Als u de accountfuncties in een onveilig openbaar netwerk gebruikt of de meldingsfunctie heeft geïnstalleerd, kan uw wachtwoord worden blootgesteld aan aanvallers in uw netwerk. + Navigatie openen + Navigatie sluiten + Zoekresultaten + Bibliotheekkeuze + Uw bibliotheek wordt nog niet ondersteund? Stel voor om het op te nemen! + Stel bibliotheek voor + Plaats + Bibliotheek naam + e.g. \"Openbare bibliotheek\", \"Uni bibliotheek\", \"DNK Assen\", … + Opmerking + Zend + Mail app selecteren… + Bibliotheek zoeken… + Zoeken + Toon meer zoekvelden + Toon minder zoekvelden + Ik ben geinteresseerd om te helpen + Bibliotheek suggestie + Omslagafbeelding + Play Store + Icon + Verlengen + Reservering verwijderen + Lenen + Materiaalkeuze + Status + Vrij zoeken + Geen zoekvelden gevonden. + Fout opgetreden. Probeer een zoekopdracht uit te voeren om dit probleem op te lossen. + Bij het controleren van uw accountgegevens gaf de bibliotheek het volgende bericht: \ "% s \" \ n \ nWilt u de accountgegevens toch opslaan? + Er kon geen verbinding worden gemaakt met de bibliotheek-server om uw accountgegevens te controleren. Wil je de accountgegevens toch bewaren? + Zoeken en account + Alleen zoeken + Cache opschonen + Opgeslagen metadata verwijderen + Sync service opstarten + Versie + Website + www.opacapp.net + Ontwikkelaar + Feedback + Support + https://opac.app/en/support/ + Applicatie beoordelen + Andere + Source Code + Laden… + Bibliotheekdata verwerken… + Actuele bibliotheeklijst laden… + Signatuur + URL + Terugbrengdatum + Plaats + Afdeling + Uitgave + Reserveringen + Barcode + Formulier leegmaken + Titel + Auteur + Titel en Auteur + tot + Ga naar details + NFC-zoeken beschikbaar + Het is bekend dat deze bibliotheek NFC-zoeken ondersteunt. Dit betekent dat terwijl + je bent op de hoofdpagina van de app, je kunt fysiek met de achterkant van je apparaat op een van de + de boeken van de bibliotheek (of andere media) en de app zal de details direct tonen. Dit + functie werkt met kleine stickers met NFC-technologie op de achterkant van het boek of + onder de voor- of achteromslag. De functie kan worden beïnvloed door de manier waarop u de uwe plaatst + apparaat in het boek of accessoires zoals smartphonehoesjes en zijn mogelijk niet voor iedereen beschikbaar + media in de bibliotheek. + + NFC-zoeken inschakelen? + Nee bedankt + NFC-zoeken ingeschakeld. U kunt dit wijzigen in de instellingen. + NFC-zoeken kan ingeschakeld worden in de instellingen. + NFC logo + Houd er rekening mee dat, afhankelijk van de regels van uw bibliotheek, + er toeslagen kunnen gelden voor reserveringen. + Houd er rekening mee dat, afhankelijk van de regels van uw bibliotheek, + er toeslagen kunnen gelden voor verlengingen. + Niet meer tonen + Doorgaan + Repeat notifications + Happy Birthday Opac App! + This May, our app turned five years old. We\'re celebrating the birthday with a new logo and want to thank all of you for all the feedback that we received. + If you want to help us keep the app sustainable in the future, talk to your library: By buying the Plus Edition of the app, they enable us to continue developing this app, and at the same time this unlocks a set of useful features for you. Check our website www.opacapp.net for more details! + Account data van %1$s tot %2$s + Titel + Auteur + Soort materiaal + Status + Barcode + Terugbrengdatum + Eigen Vestiging + Uitleen Vestiging + Afhaaldatum + Afloopdatum + Vestiging + Tik op de pijl hierboven om tussen accounts te wisselen. + Begrepen + Uit favorieten verwijderd + Ongedaan maken + Print + Wacht tot de details zijn geladen + Bibliotheekgegevens + Update bibliotheekgegevens + Reset bibliotheekgegevens + naar de statsus van de laatste app update + Updating bibliotheekgegevens + Geen ge-update bibliotheekgegevens gevonden. + Data ge-update voor %d bibliotheken. + Bibliotheekdata kon niet worden ge-update. + Laatste update %s + Nog geen data ge-download + Herstelde bibliotheekgegevens van de laatste app-update + Helaas is de bibliotheek die u gebruikt uit de app verwijderd. De reden hiervoor kan zijn dat de bibliotheek is overgestapt op een nieuw softwaresysteem waarmee de app niet compatibel is of dat de bibliotheek contact met ons heeft opgenomen en expliciet heeft aangegeven dat ze willen worden verwijderd via de app. U kunt contact met ons opnemen via https://opac.app/en/support/ voor meer informatie. + anoniem (alleen zoeken) + met inloggegevens (zoeken en account) + Voer uw wachtwoord in. + Voer uw lener ID in. + Welkom in Web Opac App! + Veeg naar links voor meer informatie. + Meldingen + U kunt meldingen inschakelen in de app-instellingen om een herinnering te ontvangen wanneer uitgeleende boeken moeten worden ingeleverd. + 1000+ bibliotheken + Deze app ondersteunt meer dan 1.000 bibliotheken van over de hele wereld. Selecteer de jouwe of stel het voor als het nog niet op de lijst staat! + (geen titel) + Omslagafbeeldingen over mobiele data laden + Omslagafbeeldingen worden geladen en indien beschikbaar weergegeven + Omslagafbeeldingen alleen over WiFi laden + U kunt ook naar beneden vegen om de gegevens te vernieuwen. + We bieden geen gratis ondersteuning van de app voor het gebruik in deze bibliotheek, problemen die in de toekomst kunnen optreden zullen daarom mogelijkerwijs niet worden opgelost. + meer info + Zoekbereik + Aanwezig + Reserveren mogelijk + Alleen inkijken, niet lenen + Gereserveerd + Uitgeleend + Is besteld + Niet beschikbaar + In behandeling + Afgehandeld + In behandeling + Staat klaar + Terug bij vestiging + Onbekend + Ophalen bij thuis vestiging? + Andere vestiging + Alternatieve ophaallocatie + Reserverings kosten en/of wachtrij + Ophalen op andere locatie +
diff --git a/opacclient/opacapp/src/main/res/values-nl/strings_api_errors.xml b/opacclient/opacapp/src/main/res/values-nl/strings_api_errors.xml new file mode 100644 index 000000000..beb933100 --- /dev/null +++ b/opacclient/opacapp/src/main/res/values-nl/strings_api_errors.xml @@ -0,0 +1,89 @@ + + + + + This library only supports one search criterion. + This library only supports up to %d search criteria. + + You haven\'t input any search criteria. + You used a combination of search criteria that is not supported by this library. Please try another search query. + Unknown Error. Please check if your login data is correct. + Unknown Error: \"%s\" Please check if your login data is correct. + Unknown error. + Unknown error: \"%s\" + Internal Error. + Internal Error: \"%s\" + Login failed. + Account could not be loaded. + Connection error. + lent until + Subtitle + Which copy do you want to reserve/order? (already available copies will be ordered) + There is no reservable copy. + Details could not be loaded. Please try again. + Error + Download + warnings + renew. + renewal no longer possible + renewal not possible + not yet renewable + The user data you entered is wrong. + Sort order + Default order + By year (descending) + By category (ascending) + By year (descending) + By category (descending) + Interlibrary: %s + Stacks: %s + Provision: %s + This feature is not supported in this library. + This reservation might cost you a fee. + + %d reservation + %d reservations + + + res. at %s + Link + Status + + Geen + Boek + CD + Software CD + Muziek CD + DVD + Film + Luisterboek + package + console game + eBook + sheet music + package of books + Onbekend + Krant + Bordspel + school version + map + Blu-Ray Disc + audio cassette + Kunst + Tijdschrift + game voor Wii console + game voor Nintendo console + game voor PlayStation + game voor XBox + LP + MP3 + URL + eVideo + eDoc + eAudio + Boetes: %s + Alles + Omschrijving + Afhaalklaar + The library is asking you to change your password. Please first log in on the library website to change your password, and then enter the new password in the app. + diff --git a/opacclient/opacapp/src/main/res/values/strings.xml b/opacclient/opacapp/src/main/res/values/strings.xml index 1a9863dec..98aafae8c 100644 --- a/opacclient/opacapp/src/main/res/values/strings.xml +++ b/opacclient/opacapp/src/main/res/values/strings.xml @@ -349,5 +349,23 @@ Renewable due media are being renewed… There are no renewable due items. An anonymous account was created for your. - + Search scope + Available + Hold allowed + Only for reference + On hold + On loan + On order + Not available + Active + Closed + In transport + Received + Returned to branch + Unknown + Pick up at home branch? + Different branch + Alternative pickup location + Reservation costs and/or queue + Pickup at different location