package io.github.azagniotov.stubby4j.stubs; import io.github.azagniotov.stubby4j.annotations.CoberturaIgnore; import io.github.azagniotov.stubby4j.annotations.VisibleForTesting; import io.github.azagniotov.stubby4j.utils.ReflectionUtils; import io.github.azagniotov.stubby4j.utils.StringUtils; import java.util.Collection; import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import static io.github.azagniotov.generics.TypeSafeConverter.asCheckedLinkedList; import static io.github.azagniotov.stubby4j.stubs.StubResponse.okResponse; public class StubHttpLifecycle implements ReflectableStub { private final AtomicInteger responseSequencedIdCounter = new AtomicInteger(0); private final String completeYAML; private final StubRequest request; private final Object response; private final String requestAsYAML; private final String responseAsYAML; private StubHttpLifecycle( final StubRequest request, final Object response, final String requestAsYAML, final String responseAsYAML, final String completeYAML) { this.request = request; this.response = response; this.requestAsYAML = requestAsYAML; this.responseAsYAML = responseAsYAML; this.completeYAML = completeYAML; } public StubRequest getRequest() { return request; } public StubResponse getResponse(final boolean incrementSequencedResponseId) { if (response instanceof StubResponse) { return (StubResponse) response; } final List<StubResponse> stubResponses = asCheckedLinkedList(this.response, StubResponse.class); if (stubResponses.isEmpty()) { return okResponse(); } if (incrementSequencedResponseId) { final int responseSequencedId = responseSequencedIdCounter.getAndIncrement(); responseSequencedIdCounter.compareAndSet(stubResponses.size(), 0); return stubResponses.get(responseSequencedId); } return stubResponses.get(responseSequencedIdCounter.get()); } public int getNextSequencedResponseId() { return responseSequencedIdCounter.get(); } public List<StubResponse> getResponses() { if (response instanceof StubResponse) { return new LinkedList<>(Collections.singletonList((StubResponse) response)); } return asCheckedLinkedList(this.response, StubResponse.class); } boolean isAuthorizationRequired() { return request.isSecured(); } @VisibleForTesting String getRawHeaderAuthorization() { return request.getRawHeaderAuthorization(); } @VisibleForTesting String getStubbedHeaderAuthorization(final StubbableAuthorizationType stubbedAuthorizationHeaderType) { return request.getStubbedHeaderAuthorization(stubbedAuthorizationHeaderType); } boolean isIncomingRequestUnauthorized(final StubHttpLifecycle assertingLifecycle) { final String stubbedHeaderAuthorization = getStubbedHeaderAuthorization(request.getStubbedAuthorizationType()); return !stubbedHeaderAuthorization.equals(assertingLifecycle.getRawHeaderAuthorization()); } public String getResourceId() { return getResponses().get(0).getResourceIDHeader(); } void setResourceId(final int resourceId) { getResponses().forEach(response -> response.addResourceIDHeader(resourceId)); } /** * @see StubRequest#getUrl() */ public String getUrl() { return request.getUrl(); } /** * Do not remove this method if your IDE complains that it is unused. * It is used by {@link ReflectionUtils} at runtime when fetching content for Ajax response */ public String getCompleteYAML() { return completeYAML; } /** * Do not remove this method if your IDE complains that it is unused. * It is used by {@link ReflectionUtils} at runtime when fetching content for Ajax response */ public String getRequestAsYAML() { return requestAsYAML; } /** * Do not remove this method if your IDE complains that it is unused. * It is used by {@link ReflectionUtils} at runtime when fetching content for Ajax response */ public String getResponseAsYAML() { return responseAsYAML; } public String getAjaxResponseContent(final StubTypes stubType, final String propertyName) throws Exception { switch (stubType) { case REQUEST: return StringUtils.objectToString(ReflectionUtils.getPropertyValue(request, propertyName)); case RESPONSE: return StringUtils.objectToString(ReflectionUtils.getPropertyValue(getResponse(false), propertyName)); default: return StringUtils.objectToString(ReflectionUtils.getPropertyValue(this, propertyName)); } } public String getAjaxResponseContent(final String propertyName, final int sequencedResponseId) throws Exception { final List<StubResponse> allResponses = getResponses(); final StubResponse sequencedResponse = allResponses.get(sequencedResponseId); return StringUtils.objectToString(ReflectionUtils.getPropertyValue(sequencedResponse, propertyName)); } @Override @CoberturaIgnore public int hashCode() { return this.request.hashCode(); } @Override @CoberturaIgnore public boolean equals(final Object o) { if (this == o) { return true; } if (!(o instanceof StubHttpLifecycle)) { return false; } final StubHttpLifecycle that = (StubHttpLifecycle) o; // The 'this' is actually the incoming asserting StubRequest, the 'that' is the stubbed one return this.request.equals(that.request); } public static class Builder { private StubRequest request; private Object response; private String completeYAML; private String requestAsYAML; private String responseAsYAML; public Builder() { this.request = null; this.response = okResponse(); this.completeYAML = null; this.requestAsYAML = null; this.responseAsYAML = null; } public Builder withRequest(final StubRequest request) { this.request = request; return this; } public Builder withResponse(final Object response) { if (response instanceof StubResponse || response instanceof Collection) { this.response = response; } else { throw new IllegalArgumentException("Trying to set response of the wrong type"); } return this; } public Builder withRequestAsYAML(final String requestAsYAML) { this.requestAsYAML = requestAsYAML; return this; } public Builder withResponseAsYAML(final String responseAsYAML) { this.responseAsYAML = responseAsYAML; return this; } public Builder withCompleteYAML(final String completeYAML) { this.completeYAML = completeYAML; return this; } public Builder withResourceId(final int resourceId) { getResponses().forEach(response -> response.addResourceIDHeader(resourceId)); return this; } public StubHttpLifecycle build() { final StubHttpLifecycle stubHttpLifecycle = new StubHttpLifecycle(request, response, requestAsYAML, responseAsYAML, completeYAML); this.request = null; this.response = okResponse(); this.completeYAML = null; this.requestAsYAML = null; this.responseAsYAML = null; return stubHttpLifecycle; } private List<StubResponse> getResponses() { if (response instanceof StubResponse) { return new LinkedList<>(Collections.singletonList((StubResponse) response)); } return asCheckedLinkedList(this.response, StubResponse.class); } } }