Passed
Push — master ( 363c08...6972ed )
by Filip
02:17
created

representsEnum(StringSchema)   A

Complexity

Conditions 1

Size

Total Lines 2
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 2
dl 0
loc 2
rs 10
c 0
b 0
f 0
1
package com.hltech.vaunt.validator;
2
3
import com.fasterxml.jackson.module.jsonSchema.JsonSchema;
4
import com.fasterxml.jackson.module.jsonSchema.types.ObjectSchema;
5
import com.fasterxml.jackson.module.jsonSchema.types.SimpleTypeSchema;
6
import com.fasterxml.jackson.module.jsonSchema.types.StringSchema;
7
import com.hltech.vaunt.core.domain.model.Contract;
8
import com.hltech.vaunt.core.domain.model.DestinationType;
9
import com.hltech.vaunt.core.domain.model.Service;
10
11
import java.util.List;
12
import java.util.Map;
13
import java.util.Optional;
14
import java.util.stream.Collectors;
15
16
public class VauntValidator {
17
18
    public List<ValidationResult> validate(Service consumer, Service provider) {
19
        return consumer.getExpectations().getProviderNameToContracts().get(provider.getName()).stream()
20
                .map(consumerContract -> validateWithMatchingProviderContract(
21
                        consumerContract, provider.getCapabilities().getContracts()))
22
                .collect(Collectors.toList());
23
    }
24
25
    public List<ValidationResult> validate(List<Contract> expectations, List<Contract> capabilities) {
26
        return expectations.stream()
27
                .map(consumerContract -> validateWithMatchingProviderContract(consumerContract, capabilities))
28
                .collect(Collectors.toList());
29
    }
30
31
    private ValidationResult validateWithMatchingProviderContract(Contract consumerContract,
32
                                                                  List<Contract> providerContracts) {
33
        List<Contract> contracts = providerContracts.stream()
34
                .filter(providerContract -> isEndpointMatching(consumerContract, providerContract))
35
                .collect(Collectors.toList());
36
37
        if (contracts.isEmpty()) {
38
            return ValidationResult.failure(consumerContract, ValidationError.MISSING_ENDPOINT);
39
        }
40
41
        Optional<Contract> matchingProviderContract = contracts.stream()
42
                .filter(providerContract -> isSchemaAndIdMatching(consumerContract.getDestinationType(),
43
                        consumerContract.getBody(), providerContract.getBody()))
44
                .findFirst();
45
46
        return matchingProviderContract
47
                .map(contract -> ValidationResult.success(consumerContract))
48
                .orElseGet(() -> ValidationResult.failure(consumerContract, contracts, ValidationError.WRONG_SCHEMA));
49
50
    }
51
52
    private boolean isEndpointMatching(Contract firstContract, Contract secondContract) {
53
        return isTmpQueueMatching(firstContract, secondContract)
54
                || (isDstTypeMatching(firstContract, secondContract)
55
                && isDstNameMatching(firstContract, secondContract));
56
    }
57
58
    private boolean isTmpQueueMatching(Contract firstContract, Contract secondContract) {
59
        return firstContract.getDestinationType() == DestinationType.TEMPORARY_QUEUE
60
                && isDstTypeMatching(firstContract, secondContract);
61
    }
62
63
    private boolean isDstTypeMatching(Contract firstContract, Contract secondContract) {
64
        return firstContract.getDestinationType() == secondContract.getDestinationType();
65
    }
66
67
    private boolean isDstNameMatching(Contract firstContract, Contract secondContract) {
68
        return firstContract.getDestinationName().equals(secondContract.getDestinationName());
69
    }
70
71
    private boolean isSchemaAndIdMatching(DestinationType dstType, JsonSchema consumerBody, JsonSchema providerBody) {
72
        if (!consumerBody.getId().equals(providerBody.getId())) {
73
            return false;
74
        }
75
76
        return isSchemaMatching(dstType, consumerBody, providerBody);
77
    }
78
79
    private boolean isSchemaMatching(DestinationType dstType, JsonSchema consumerBody, JsonSchema providerBody) {
80
        if (isStringSchema(consumerBody) && isStringSchema(providerBody)) {
81
            return compareEnumSchema(dstType, consumerBody, providerBody);
82
        }
83
84
        if (isObjectSchema(consumerBody) && isObjectSchema(providerBody)) {
85
            return compareObjectSchema(dstType, consumerBody.asObjectSchema(), providerBody.asObjectSchema());
86
        }
87
88
        return consumerBody.equals(providerBody);
89
    }
90
91
    private boolean isObjectSchema(JsonSchema schema) {
92
        return schema.asObjectSchema() != null;
93
    }
94
95
    private boolean isStringSchema(JsonSchema schema) {
96
        return schema.asStringSchema() != null;
97
    }
98
99
    private boolean compareEnumSchema(DestinationType dstType, JsonSchema consumerBody, JsonSchema providerBody) {
100
        return compareStringSchemaPart(dstType, consumerBody.asStringSchema(), providerBody.asStringSchema())
101
                && compareSimpleTypeSchemaPart(consumerBody.asSimpleTypeSchema(), providerBody.asSimpleTypeSchema())
102
                && compareJsonSchemaPart(consumerBody, providerBody);
103
    }
104
105
    private boolean compareStringSchemaPart(DestinationType dstType,
106
                                            StringSchema consumerBody,
107
                                            StringSchema providerBody) {
108
        return equals(consumerBody.getMaxLength(), providerBody.getMaxLength())
109
                && equals(consumerBody.getMinLength(), providerBody.getMinLength())
110
                && equals(consumerBody.getPattern(), providerBody.getPattern())
111
                && equals(consumerBody.getFormat(), providerBody.getFormat())
112
                && compareEnum(dstType, consumerBody, providerBody);
113
    }
114
115
    private boolean compareSimpleTypeSchemaPart(SimpleTypeSchema consumerBody, SimpleTypeSchema providerBody) {
116
        return equals(consumerBody.getDefault(), providerBody.getDefault())
117
                && equals(consumerBody.getTitle(), providerBody.getTitle())
118
                && equals(consumerBody.getPathStart(), providerBody.getPathStart())
119
                && equals(consumerBody.getLinks(), providerBody.getLinks());
120
    }
121
122
    private boolean compareJsonSchemaPart(JsonSchema consumerBody, JsonSchema providerBody) {
123
        return equals(consumerBody.getId(), providerBody.getId())
124
                && equals(consumerBody.getRequired(), providerBody.getRequired())
125
                && equals(consumerBody.getReadonly(), providerBody.getReadonly())
126
                && equals(consumerBody.get$ref(), providerBody.get$ref())
127
                && equals(consumerBody.get$schema(), providerBody.get$schema())
128
                && equals(consumerBody.getDisallow(), providerBody.getDisallow())
129
                && equals(consumerBody.getExtends(), providerBody.getExtends());
130
    }
131
132
    private boolean compareEnum(DestinationType dstType, StringSchema consumerBody, StringSchema providerBody) {
133
        switch (dstType) {
134
            case QUEUE:
135
            case TEMPORARY_QUEUE:
136
                if (representsString(consumerBody) && representsEnum(providerBody)) {
137
                    return false;
138
                }
139
140
                if (representsEnum(consumerBody) && representsEnum(providerBody)) {
141
                    return providerBody.getEnums().containsAll(consumerBody.getEnums());
142
                }
143
144
                return true;
145
            case TOPIC:
146
                if (representsString(providerBody) && representsEnum(consumerBody)) {
147
                    return false;
148
                }
149
150
                if (representsEnum(providerBody) && representsEnum(consumerBody)) {
151
                    return consumerBody.getEnums().containsAll(providerBody.getEnums());
152
                }
153
154
                return true;
155
            default:
156
                throw new RuntimeException("Unknown JMS destination type"); // TODO: handle
157
        }
158
    }
159
160
    private boolean representsEnum(StringSchema body) {
161
        return body.getEnums().size() > 0;
162
    }
163
164
    private boolean representsString(StringSchema body) {
165
        return body.getEnums().size() == 0;
166
    }
167
168
    private boolean compareObjectSchema(DestinationType dstType, ObjectSchema consumerBody, ObjectSchema providerBody) {
169
        return equals(consumerBody.getAdditionalProperties(), providerBody.getAdditionalProperties())
170
                && equals(consumerBody.getDependencies(), providerBody.getDependencies())
171
                && equals(consumerBody.getPatternProperties(), providerBody.getPatternProperties())
172
                && compareObjectProperties(dstType, consumerBody.getProperties(), providerBody.getProperties());
173
    }
174
175
    private boolean compareObjectProperties(DestinationType dstType,
176
                                            Map<String, JsonSchema> consumerProperties,
177
                                            Map<String, JsonSchema> providerProperties) {
178
        return consumerProperties.keySet().equals(providerProperties.keySet())
179
                && consumerProperties.keySet().stream()
180
                .allMatch(key -> isSchemaMatching(
181
                        dstType, consumerProperties.get(key), providerProperties.get(key)));
182
    }
183
184
    private boolean equals(Object object1, Object object2) {
185
        if (object1 == null) {
186
            return object2 == null;
187
        } else {
188
            return object1.equals(object2);
189
        }
190
    }
191
}
192