1 package org.onap.sdc.dcae.ves;
3 import com.google.gson.JsonElement;
4 import com.google.gson.annotations.SerializedName;
5 import org.apache.commons.collections.CollectionUtils;
6 import org.apache.commons.collections.MapUtils;
7 import org.apache.commons.lang.StringUtils;
11 public class VesDataTypeDefinition {
13 private static final String jsonReferencePrefix = "#/definitions/";
15 private String description;
16 private String format;
18 private Map<String, VesDataTypeDefinition> properties;
19 private List<String> required = new ArrayList<>();
20 @SerializedName("enum")
21 private List<String> enums;
22 @SerializedName("default")
23 private JsonElement defaultValue;
24 private VesDataItemsDefinition items;
25 @SerializedName("$ref")
28 public String getType() {
32 public void setType(String type) {
36 public String getDescription() {
40 public void setDescription(String description) {
41 this.description = description;
44 public String getFormat() {
48 public void setFormat(String format) {
52 public String getTitle() {
56 public void setTitle(String title) {
60 public Map<String, VesDataTypeDefinition> getProperties() {
64 public void setProperties(Map<String, VesDataTypeDefinition> properties) {
65 this.properties = properties;
68 public List<String> getRequired() {
72 public void setRequired(List<String> required) {
73 this.required = required;
76 public List<String> getEnums() {
80 public void setEnums(List<String> enums) {
84 public JsonElement getDefaultValue() {
88 public void setDefaultValue(JsonElement defaultValue) {
89 this.defaultValue = defaultValue;
92 public VesDataItemsDefinition getItems() {
96 public void setItems(VesDataItemsDefinition items) {
100 public String getRef() {
104 public void setRef(String ref) {
108 protected boolean hasReference() {
109 return StringUtils.isNotBlank(getRef());
112 protected boolean itemsContainReference() {
113 return CollectionUtils.isNotEmpty(getItems()) && getItems().stream().anyMatch(VesDataTypeDefinition::containsAnyReferenceItem);
116 protected boolean propertiesContainReference() {
117 return MapUtils.isNotEmpty(getProperties()) && getProperties().values().stream().anyMatch(VesDataTypeDefinition::containsAnyReferenceItem);
120 protected boolean containsAnyReferenceItem() {
121 return hasReference() || itemsContainReference() || propertiesContainReference();
124 protected String getJsonRefPointer() {
125 return getRef().replace(jsonReferencePrefix, "");
128 private void addReferenceItem(Set<String> allRefs) {
129 if (hasReference()) {
130 allRefs.add(getJsonRefPointer());
134 private Set<String> extractAllReferenceTokens() {
135 Set<String> allRefs = new HashSet<>();
136 extractReferenceTokens(allRefs);
140 private void extractReferenceTokens(Set<String> allRefs) {
142 addReferenceItem(allRefs);
143 if (itemsContainReference()) {
144 getItems().forEach(item -> item.extractReferenceTokens(allRefs));
146 if (propertiesContainReference()) {
147 getProperties().values().forEach(property -> property.extractReferenceTokens(allRefs));
151 protected boolean isResolvable(Map<String, VesDataTypeDefinition> resolvedTypes) {
152 return resolvedTypes.keySet().containsAll(extractAllReferenceTokens());
155 private void resolveReference(Map<String, VesDataTypeDefinition> resolvedTypes) {
156 if (hasReference()) {
157 VesDataTypeDefinition other = resolvedTypes.get(getJsonRefPointer());
158 setType(other.getType());
159 setRef(other.getRef());
160 setDefaultValue(other.getDefaultValue());
161 setDescription(other.getDescription());
162 setEnums(other.getEnums());
163 setProperties(other.getProperties());
164 setFormat(other.getFormat());
165 setRequired(other.getRequired());
166 setItems(other.getItems());
167 setTitle(other.getTitle());
171 private void resolveItemReferences(Map<String, VesDataTypeDefinition> resolvedTypes) {
172 if (itemsContainReference()) {
173 for (VesDataTypeDefinition item : getItems()) {
174 item.resolveAllReferences(resolvedTypes);
179 private void resolvePropertyReferences(Map<String, VesDataTypeDefinition> resolvedTypes) {
180 if (propertiesContainReference()) {
181 for (VesDataTypeDefinition property : getProperties().values()) {
182 property.resolveAllReferences(resolvedTypes);
187 // the reference resolver is called on each VesDataTypeDefinition after it passes the 'isResolvable' validation, affirming that all its references(direct/properties/items) point to a resolved VesDataTypeDefinition (has no references)
188 protected void resolveAllReferences(Map<String, VesDataTypeDefinition> resolvedTypes) {
189 resolveReference(resolvedTypes);
190 resolveItemReferences(resolvedTypes);
191 resolvePropertyReferences(resolvedTypes);
194 private String validateType() {
195 return null == type? null : VesSimpleTypesEnum.getSimpleTypes().contains(type) ? null : "invalid type declaration: " + type;
198 private String validateRequired() {
199 String invalid = null == type? null : !type.equals(VesSimpleTypesEnum.OBJECT.getType()) ? null : required.stream().filter(r -> !properties.keySet().contains(r)).findAny().orElse(null);
200 return StringUtils.isBlank(invalid) ? invalid : "invalid required entry: " + invalid;
203 // returns error message detailing invalid 'type' or 'required' fields (null for success)
204 protected String validate() {
205 String error = validateType();
206 if (StringUtils.isBlank(error))
207 error = validateRequired();
208 if (StringUtils.isBlank(error) && CollectionUtils.isNotEmpty(items))
209 error = validateItems();
210 if(StringUtils.isBlank(error) && MapUtils.isNotEmpty(properties))
211 error = validateProperties();
215 private String validateItems(){
217 for (VesDataTypeDefinition def : items) {
218 if (StringUtils.isBlank(error))
219 error = def.validate();
226 private String validateProperties(){
228 for (VesDataTypeDefinition def : properties.values()) {
229 if (StringUtils.isBlank(error))
230 error = def.validate();
239 public boolean equals(Object obj) {
242 if (null == obj || getClass() != obj.getClass())
244 VesDataTypeDefinition other = (VesDataTypeDefinition) obj;
245 return Objects.equals(type, other.type) &&
246 Objects.equals(description, other.description) &&
247 Objects.equals(format, other.format) &&
248 Objects.equals(title, other.title) &&
249 Objects.equals(required, other.required) &&
250 Objects.equals(enums, other.enums) &&
251 Objects.equals(defaultValue, other.defaultValue) &&
252 Objects.equals(items, other.items) &&
253 Objects.equals(properties, other.properties) &&
254 Objects.equals(ref, other.ref);
257 @Override public int hashCode() {
258 int result = type != null ? type.hashCode() : 0;
259 result = 31 * result + (description != null ? description.hashCode() : 0);
260 result = 31 * result + (format != null ? format.hashCode() : 0);
261 result = 31 * result + (title != null ? title.hashCode() : 0);
262 result = 31 * result + (properties != null ? properties.hashCode() : 0);
263 result = 31 * result + (required != null ? required.hashCode() : 0);
264 result = 31 * result + (enums != null ? enums.hashCode() : 0);
265 result = 31 * result + (defaultValue != null ? defaultValue.hashCode() : 0);
266 result = 31 * result + (items != null ? items.hashCode() : 0);
267 result = 31 * result + (ref != null ? ref.hashCode() : 0);