Skip to content

Commit

Permalink
Merge f6f58ea into ea107c5
Browse files Browse the repository at this point in the history
  • Loading branch information
Felipe444 authored Dec 24, 2018
2 parents ea107c5 + f6f58ea commit 41cf63d
Show file tree
Hide file tree
Showing 12 changed files with 245 additions and 65 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import static java.util.stream.Collectors.toMap;

@Entity
@Getter
@Access(AccessType.FIELD)
public class ServiceContracts {

Expand All @@ -42,21 +43,17 @@ public class ServiceContracts {
protected ServiceContracts() {
}

public ServiceContracts(String name, String version, Map<String, String> capabilitiesPerProtocol, Map<String, Map<String, String>> expectationsPerProvider) {
public ServiceContracts(String name, String version, Map<String, Contract> capabilitiesPerProtocol, Map<String, Map<String, Contract>> expectationsPerProvider) {
this.id = new ServiceContractsId(name, version);
this.capabilitiesPerProtocol = capabilitiesPerProtocol.entrySet().stream().collect(toMap(
entry -> entry.getKey(),
entry -> new Contract(entry.getValue())
));
this.capabilitiesPerProtocol = capabilitiesPerProtocol;
this.expectations = newHashMap();
for (Entry<String, Map<String, String>> expectationsPerProviderEntry : expectationsPerProvider.entrySet()) {
for (Entry<String, Map<String, Contract>> expectationsPerProviderEntry : expectationsPerProvider.entrySet()) {
String provider = expectationsPerProviderEntry.getKey();
Map<String, String> expectationsPerProtocol = expectationsPerProviderEntry.getValue();
Map<String, Contract> expectationsPerProtocol = expectationsPerProviderEntry.getValue();

for (Entry<String, String> expectationsPerProtocolEntry : expectationsPerProtocol.entrySet()) {
for (Entry<String, Contract> expectationsPerProtocolEntry : expectationsPerProtocol.entrySet()) {
String protocol = expectationsPerProtocolEntry.getKey();
String protocolExpectation = expectationsPerProtocolEntry.getValue();
this.expectations.put(new ProviderProtocol(provider, protocol), new Contract(protocolExpectation));
this.expectations.put(new ProviderProtocol(provider, protocol), expectationsPerProtocolEntry.getValue());
}
}
}
Expand All @@ -70,19 +67,19 @@ public String getVersion() {
}


public <C> Optional<C> getCapabilities(String communicationInterface, Function<String, C> deserializer) {
public <C> Optional<C> getMappedCapabilities(String communicationInterface, Function<String, C> deserializer) {
return ofNullable(this.capabilitiesPerProtocol.get(communicationInterface))
.map(Contract::getValue)
.map(deserializer);
}

public <E> Optional<E> getExpectations(String providerName, String communicationInterface, Function<String, E> deserializer) {
public <E> Optional<E> getMappedExpectations(String providerName, String communicationInterface, Function<String, E> deserializer) {
return ofNullable(this.expectations.get(new ProviderProtocol(providerName, communicationInterface)))
.map(Contract::getValue)
.map(deserializer);
}

public <E> Map<String, E> getExpectations(String communicationInterface, Function<String, E> deserializer) {
public <E> Map<String, E> getMappedExpectations(String communicationInterface, Function<String, E> deserializer) {
return this.expectations.entrySet()
.stream()
.filter(expectationsEntry -> expectationsEntry.getKey().getProtocol().equals(communicationInterface))
Expand All @@ -92,14 +89,14 @@ public <E> Map<String, E> getExpectations(String communicationInterface, Functio
));
}

public Map<String, String> getCapabilities() {
public Map<String, String> getMappedCapabilities() {
return this.capabilitiesPerProtocol.entrySet().stream().collect(toMap(
e -> e.getKey(),
e -> e.getValue().getValue()
));
}

public Map<String, Map<String, String>> getExpectations() {
public Map<String, Map<String, String>> getMappedExpectations() {
HashMap<String, Map<String, String>> result = newHashMap();
for (Entry<ProviderProtocol, Contract> e : this.expectations.entrySet()) {
ProviderProtocol pp = e.getKey();
Expand Down Expand Up @@ -139,8 +136,7 @@ public static class ProviderProtocol {
@NoArgsConstructor
@Access(AccessType.FIELD)
public static class Contract implements Serializable {

private String value;

private String mimeType;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public List<CapabilitiesValidationResult> validateCapabilities(ServiceContracts

private CapabilitiesValidationResult validateCapabilities(C capabilities, String providerName, ServiceContracts consumer) {
List<InteractionValidationResult> validatedInteractions = consumer
.getExpectations(providerName, this.communicationInterface, this::asExpectations)
.getMappedExpectations(providerName, this.communicationInterface, this::asExpectations)
.map(expectations -> validate(expectations, capabilities))
.orElse(emptyList());

Expand Down Expand Up @@ -75,7 +75,7 @@ private Stream<? extends ExpectationValidationResult> validateExpectations(E exp

private ExpectationValidationResult validateExpectations(E expectations, ServiceContracts provider) {
List<InteractionValidationResult> validatedInteractions = provider
.getCapabilities(this.communicationInterface, this::asCapabilities)
.getMappedCapabilities(this.communicationInterface, this::asCapabilities)
.map(capabilities -> validate(expectations, capabilities))
.orElseGet(() -> newArrayList(
new InteractionValidationResult(
Expand All @@ -101,11 +101,11 @@ private ExpectationValidationResult createProviderNotAvailableResult(String prov
}

public Optional<C> extractCapabilities(ServiceContracts serviceContracts) {
return serviceContracts.getCapabilities(this.communicationInterface, this::asCapabilities);
return serviceContracts.getMappedCapabilities(this.communicationInterface, this::asCapabilities);
}

public Map<String, E> extractExpectations(ServiceContracts testedServiceContracts) {
return testedServiceContracts.getExpectations(this.communicationInterface, this::asExpectations);
return testedServiceContracts.getMappedExpectations(this.communicationInterface, this::asExpectations);
}

public abstract C asCapabilities(String rawCapabilities);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.google.common.collect.Maps.newHashMap;
import static java.util.stream.Collectors.toList;

@RestController
Expand All @@ -37,14 +41,41 @@ public ServiceContractsDto create(@PathVariable(name = "provider") String provid
new ServiceContracts(
provider,
version,
form.getCapabilities(),
form.getExpectations()
map(form.getCapabilities()),
form.getExpectations().entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> map(entry.getValue())
)
)
)
));
}

@PostMapping(value = "/new/contracts/{provider}/{version:.+}", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(value = "Register contracts for a version of a service", nickname = "register contracts")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Success", response = ServiceContractsDto.class),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 500, message = "Failure")})
public NewServiceContractsDto newCreate(@PathVariable(name = "provider") String provider, @PathVariable(name = "version") String version, @RequestBody NewServiceContractsForm form) {
return newToDto(this.serviceContractsRepository.persist(
new ServiceContracts(
provider,
version,
mapToEntity(form.getCapabilities()),
form.getExpectations().entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> mapToEntity(entry.getValue())
)
)
)
));
}

@GetMapping(value = "/contracts", produces = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(value = "Get names of services with registered contracts", nickname = "get names of services")
@ApiOperation(value = "Get names of services with registered contracts", nickname = "create names of services")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Success", response = String.class, responseContainer = "list"),
@ApiResponse(code = 400, message = "Bad Request"),
Expand All @@ -54,7 +85,7 @@ public List<String> getAvailableServiceNames() {
}

@GetMapping(value = "/contracts/{serviceName}", produces = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(value = "Get versions of a service with registered contracts", nickname = "get versions of a service")
@ApiOperation(value = "Get versions of a service with registered contracts", nickname = "create versions of a service")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Success", response = String.class, responseContainer = "list"),
@ApiResponse(code = 400, message = "Bad Request"),
Expand All @@ -66,26 +97,78 @@ public List<String> getServiceVersions(@PathVariable(name = "serviceName") Strin
.collect(toList());
}


@GetMapping(value = "/contracts/{provider}/{version:.+}", produces = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(value = "Register contracts for a version of a service", nickname = "register contracts")
@ApiOperation(value = "Get contracts for a version of a service", nickname = "register contracts")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Success", response = ServiceContractsDto.class),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 500, message = "Failure")})
public ServiceContractsDto create(@PathVariable(name = "provider") String provider, @PathVariable(name = "version") String version) {
public ServiceContractsDto get(@PathVariable(name = "provider") String provider, @PathVariable(name = "version") String version) {
return toDto(this.serviceContractsRepository.find(provider, version).orElseThrow(() -> new ResourceNotFoundException()));
}

private ServiceContractsDto toDto(ServiceContracts serviceContracts) {
ServiceContractsDto dto = new ServiceContractsDto();
dto.setName(serviceContracts.getName());
dto.setVersion(serviceContracts.getVersion());
@GetMapping(value = "/new/contracts/{provider}/{version:.+}", produces = MediaType.APPLICATION_JSON_VALUE)
@ApiOperation(value = "Get contracts for a version of a service", nickname = "register contracts")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Success", response = ServiceContractsDto.class),
@ApiResponse(code = 400, message = "Bad Request"),
@ApiResponse(code = 500, message = "Failure")})
public NewServiceContractsDto newGet(@PathVariable(name = "provider") String provider, @PathVariable(name = "version") String version) {
return newToDto(this.serviceContractsRepository.find(provider, version).orElseThrow(() -> new ResourceNotFoundException()));
}

private Map<String, ServiceContracts.Contract> map(Map<String, String> protocolToContractStrings) {
return protocolToContractStrings.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> new ServiceContracts.Contract(entry.getValue(), MediaType.APPLICATION_JSON_VALUE)
));
}

dto.setCapabilities(serviceContracts.getCapabilities());
dto.setExpectations(serviceContracts.getExpectations());
return dto;
private Map<String, ServiceContracts.Contract> mapToEntity(Map<String, NewServiceContractsForm.ContractForm> protocolToContractForms) {
return protocolToContractForms.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> new ServiceContracts.Contract(entry.getValue().getValue(), entry.getValue().getMimeType())
));
}

private Map<String, NewServiceContractsDto.ContractDto> mapCapabilitiesToDto(Map<String, ServiceContracts.Contract> capabilities) {
return capabilities.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> new NewServiceContractsDto.ContractDto(entry.getValue().getValue(), entry.getValue().getMimeType())
));
}

private Map<String, Map<String, NewServiceContractsDto.ContractDto>> mapExpectationsToDto(Map<ServiceContracts.ProviderProtocol, ServiceContracts.Contract> expectations) {
HashMap<String, Map<String, NewServiceContractsDto.ContractDto>> result = newHashMap();
for (Map.Entry<ServiceContracts.ProviderProtocol, ServiceContracts.Contract> e : expectations.entrySet()) {
ServiceContracts.ProviderProtocol pp = e.getKey();
ServiceContracts.Contract contract = e.getValue();
if (!result.containsKey(pp.getProvider())) {
result.put(pp.getProvider(), newHashMap());
}
result.get(pp.getProvider()).put(pp.getProtocol(), new NewServiceContractsDto.ContractDto(contract.getValue(), contract.getMimeType()));
}
return result;
}

private ServiceContractsDto toDto(ServiceContracts serviceContracts) {
return new ServiceContractsDto(
serviceContracts.getName(),
serviceContracts.getVersion(),
serviceContracts.getMappedCapabilities(),
serviceContracts.getMappedExpectations()
);
}

private NewServiceContractsDto newToDto(ServiceContracts serviceContracts) {
return new NewServiceContractsDto(
serviceContracts.getName(),
serviceContracts.getVersion(),
mapCapabilitiesToDto(serviceContracts.getCapabilitiesPerProtocol()),
mapExpectationsToDto(serviceContracts.getExpectations())
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package dev.hltech.dredd.interfaces.rest.contracts;

import lombok.Data;

import java.io.Serializable;
import java.util.Map;

@Data
public class NewServiceContractsDto {

private final String name;
private final String version;

private final Map<String, ContractDto> capabilities;
private final Map<String, Map<String, ContractDto>> expectations;

@Data
public static class ContractDto implements Serializable {
private final String value;
private final String mimeType;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package dev.hltech.dredd.interfaces.rest.contracts;

import lombok.Data;

import java.io.Serializable;
import java.util.Map;

@Data
public class NewServiceContractsForm {

private final Map<String, ContractForm> capabilities;
private final Map<String, Map<String, ContractForm>> expectations;

@Data
public static class ContractForm implements Serializable {
private final String value;
private final String mimeType;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@
@Data
public class ServiceContractsDto {

private String name;
private String version;
private final String name;
private final String version;

private Map<String, String> capabilities;
private Map<String, Map<String, String>> expectations;
private final Map<String, String> capabilities;
private final Map<String, Map<String, String>> expectations;

}
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
package dev.hltech.dredd.interfaces.rest.contracts;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Map;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ServiceContractsForm {

private Map<String, String> capabilities;
private Map<String, Map<String, String>> expectations;

private final Map<String, String> capabilities;
private final Map<String, Map<String, String>> expectations;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<databaseChangeLog
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd
http://www.liquibase.org/xml/ns/dbchangelog
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.4.xsd">

<changeSet id="add-mime-type-to-contracts-0.3" author="Filip Lazarski">
<addColumn tableName="capabilities">
<column name="mime_type" type="text"/>
</addColumn>
<addColumn tableName="expectations">
<column name="mime_type" type="text"/>
</addColumn>
</changeSet>
</databaseChangeLog>
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@

<include file="/db/changelog/db.changelog-0.1.xml"/>
<include file="/db/changelog/db.changelog-0.2.xml"/>
<include file="/db/changelog/db.changelog-0.3.xml"/>

</databaseChangeLog>
Loading

0 comments on commit 41cf63d

Please sign in to comment.