renewLoan method
Future<Try<DateTime, LcpException> >
renewLoan(
- RenewListener listener, {
- bool prefersWebPage = false,
override
Renews the loan by starting a renew LSD interaction.
@param prefersWebPage Indicates whether the loan should be renewed through a web page if available, instead of programmatically.
Implementation
@override
Future<Try<DateTime, LcpException>> renewLoan(RenewListener listener,
{bool prefersWebPage = false}) async {
// Finds the renew link according to `prefersWebPage`.
Link? findRenewLink() {
StatusDocument? status = _documents.status;
if (status == null) {
return null;
}
List<MediaType> types = [MediaType.html, MediaType.xhtml];
if (prefersWebPage) {
types.add(MediaType.lcpStatusDocument);
} else {
types.insert(0, MediaType.lcpStatusDocument);
}
for (MediaType type in types) {
Link? link = status.link(StatusRel.renew, type: type);
if (link != null) {
return link;
}
}
// Fallback on the first renew link with no media type set and assume it's a PUT action.
return status.linkWithNoType(StatusRel.renew);
}
// Programmatically renew the loan with a PUT request.
Future<ByteData> renewProgrammatically(Link link) async {
DateTime? endDate;
if (link.templateParameters.contains("end")) {
endDate = await listener.preferredEndDate(maxRenewDate);
}
Map<String, String> parameters = await _device.asQueryParameters;
if (endDate != null) {
parameters["end"] = endDate.toIso8601String();
}
Uri url = link.urlWithParams(parameters: parameters);
Try<ByteData, NetworkException> result =
await _network.fetch(url.toString(), method: Method.put);
return result.getOrElse((error) {
switch (error.status) {
case HttpStatus.badRequest:
throw LcpException.renew.renewFailed;
case HttpStatus.forbidden:
throw LcpException.renew.invalidRenewalPeriod(this.maxRenewDate);
default:
throw LcpException.renew.unexpectedServerError;
}
});
}
// Renew the loan by presenting a web page to the user.
Future<ByteData> renewWithWebPage(Link link) {
// The reading app will open the URL in a web view and return when it is dismissed.
listener.openWebPage(link.url);
Uri statusUrl;
try {
statusUrl = license.url(LicenseRel.status,
preferredType: MediaType.lcpStatusDocument);
} on LcpException {
throw LcpException.licenseInteractionNotAvailable;
}
return _network
.fetch(statusUrl.toString())
.then((value) => value.getOrThrow());
}
try {
Link? link = findRenewLink();
if (link == null) {
throw LcpException.licenseInteractionNotAvailable;
}
Future<ByteData> data;
if (link.mediaType.isHtml) {
data = renewWithWebPage(link);
} else {
data = renewProgrammatically(link);
}
_validateStatusDocument(await data);
return Try.success(_documents.license.rights.end);
// } on CancellationException {
// // Passthrough for cancelled coroutines
// rethrow;
} on Exception catch (e) {
return Try.failure(LcpException.wrap(e));
}
}