package de.rwth.idsg.steve.handler;
import de.rwth.idsg.steve.ocpp.RequestType;
import de.rwth.idsg.steve.ocpp.ResponseType;
import de.rwth.idsg.steve.ocpp.ws.data.OcppJsonError;
import de.rwth.idsg.steve.web.dto.task.RequestTask;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.xml.ws.Response;
import java.util.ArrayList;
/**
* @author Sevket Goekay <goekay@dbis.rwth-aachen.de>
* @since 21.03.2015
*/
@RequiredArgsConstructor
public abstract class AbstractOcppResponseHandler<S extends RequestType, T extends ResponseType>
implements OcppResponseHandler<S, T> {
protected final RequestTask<S> requestTask;
protected final String chargeBoxId;
private final Logger log = LoggerFactory.getLogger(getClass());
// The default initial capacity is 10. We probably won't need that much.
private ArrayList<OcppCallback<T>> callbackList = new ArrayList<>(2);
// -------------------------------------------------------------------------
// AsyncHandler
// -------------------------------------------------------------------------
@Override
public void handleResponse(Response<T> res) {
try {
processResponse(res.get());
} catch (Exception e) {
processException(e);
}
}
// -------------------------------------------------------------------------
// OcppResponseHandler
// -------------------------------------------------------------------------
@Override
public void addCallback(OcppCallback<T> cb) {
callbackList.add(cb);
}
@Override
public S getRequest() {
return requestTask.getRequest();
}
@Override
public abstract void handleResult(T response);
// -------------------------------------------------------------------------
// OcppJsonResponseHandler
// -------------------------------------------------------------------------
@Override
public void handleResponse(T response) {
processResponse(response);
}
@Override
public void handleException(Exception e) {
processException(e);
}
/**
* Even though we have an error, this object is still a valid response from charge point
* and RequestTask should treat it as such.
* {@link RequestTask#addNewError(java.lang.String, java.lang.Exception)}
* should be used when the request could not be delivered and there is a Java exception.
*/
@Override
public void handleError(OcppJsonError error) {
try {
requestTask.addNewResponse(chargeBoxId, error.toString());
} finally {
// But, as far as the callbacks are concerned, this is still a failure.
failed(error.getErrorDescription());
}
}
// -------------------------------------------------------------------------
// OcppCallback helpers
//
// OcppCallback exceptions should be handled silently, that is they should
// not take the ongoing process/thread or system down. With this, we just
// log the exception and allow the application to continue with the next
// callback in line.
// -------------------------------------------------------------------------
private void processResponse(T response) {
try {
handleResult(response);
} finally {
success(response);
}
}
private void processException(Exception e) {
try {
requestTask.addNewError(chargeBoxId, e);
} finally {
failed(e.getMessage());
}
}
private void success(T response) {
for (OcppCallback<T> c : callbackList) {
try {
c.success(response);
} catch (Exception e) {
log.error("Exception occurred in OcppCallback", e);
}
}
}
private void failed(String errorMessage) {
for (OcppCallback<T> c : callbackList) {
try {
c.failed(errorMessage);
} catch (Exception e) {
log.error("Exception occurred in OcppCallback", e);
}
}
}
}