2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
20 package org.onap.aai.introspection.tools;
22 import org.onap.aai.db.props.AAIProperties;
23 import org.onap.aai.exceptions.AAIException;
24 import org.onap.aai.introspection.Introspector;
25 import org.onap.aai.introspection.IntrospectorWalker;
26 import org.onap.aai.introspection.Visibility;
27 import org.onap.aai.introspection.Wanderer;
28 import org.onap.aai.schema.enums.PropertyMetadata;
32 public class IntrospectorValidator implements Wanderer {
35 private List<Issue> issues = null;
36 private List<IssueResolver> issueResolvers = null;
37 private boolean validateRequired = true;
38 private final int maximumDepth;
39 private int currentDepth = 0;
41 private final Set<String> relationshipChain;
43 * Instantiates a new introspector validator.
45 * @param builder the builder
47 private IntrospectorValidator(Builder builder) {
48 this.validateRequired = builder.getValidateRequired();
49 this.issueResolvers = builder.getResolvers();
50 this.maximumDepth = builder.getMaximumDepth();
51 issues = new ArrayList<>();
53 relationshipChain = new HashSet<>();
55 relationshipChain.add("relationship-list");
56 relationshipChain.add("relationship");
57 relationshipChain.add("relationship-data");
58 relationshipChain.add("related-to-property");
67 * @return true, if successful
68 * @throws AAIException
70 public boolean validate(Introspector obj) throws AAIException {
71 IntrospectorWalker walker = new IntrospectorWalker(this);
72 this.currentDepth = 0;
75 for (Issue m : issues) {
76 if (!m.getSeverity().equals(Severity.WARNING)) {
89 public List<Issue> getIssues() {
94 * Sets the issue resolvers.
96 * @param resolvers the new issue resolvers
98 public void setIssueResolvers(List<IssueResolver> resolvers) {
99 issueResolvers = new ArrayList<>();
100 for (IssueResolver resolver : resolvers) {
101 issueResolvers.add(resolver);
108 * @return true, if successful
110 public boolean resolveIssues() {
111 boolean result = true;
112 for (Issue issue : issues) {
113 for (IssueResolver resolver : issueResolvers) {
114 if (resolver.resolveIssue(issue)) {
115 issue.setResolved(true);
118 if (!issue.isResolved()) {
130 public void processComplexObj(Introspector obj) {
132 if (this.currentDepth > this.maximumDepth && !relationshipChain.contains(obj.getDbName())) {
134 this.buildMessage(Severity.CRITICAL, IssueType.EXCEEDED_ALLOWED_DEPTH, "Maximum allowed depth of this object has been exceeded on: " + obj.getDbName());
135 message.setIntrospector(obj);
138 Set<String> requiredProps = obj.getRequiredProperties();
139 Set<String> keys = obj.getKeys();
140 Set<String> props = obj.getProperties();
142 for (String prop : props) {
143 Object value = obj.getValue(prop);
144 if (keys.contains(prop)) {
147 this.buildMessage(Severity.CRITICAL, IssueType.MISSING_KEY_PROP, "Missing key property: " + prop);
148 message.setIntrospector(obj);
149 message.setPropName(prop);
152 } else if (requiredProps.contains(prop)) {
153 if (value == null && validateRequired) {
155 this.buildMessage(Severity.CRITICAL, IssueType.MISSING_REQUIRED_PROP, "Missing required property: " + prop);
156 message.setIntrospector(obj);
157 message.setPropName(prop);
162 final Optional<String> visibility = obj.getPropertyMetadata(prop, PropertyMetadata.VISIBILITY);
163 if(visibility.isPresent() && Visibility.internal.equals(Visibility.valueOf(visibility.get())) && obj.getValue(prop) != null) {
165 this.buildMessage(Severity.ERROR, IssueType.PROPERTY_NOT_VISIBLE, "client attemptted to set property not visible: " + prop);
166 message.setIntrospector(obj);
167 message.setPropName(prop);
171 final Optional<String> requires = obj.getPropertyMetadata(prop, PropertyMetadata.REQUIRES);
172 if (requires.isPresent() && (obj.getValue(prop) != null && obj.getValue(requires.get()) == null)) {
174 this.buildMessage(Severity.CRITICAL, IssueType.DEPENDENT_PROP_NOT_FOUND, prop + " requires " + requires.get() + " to also be popluated.");
175 message.setIntrospector(obj);
176 message.setPropName(prop);
181 if (!relationshipChain.contains(obj.getDbName())) {
191 public void processPrimitive(String propName, Introspector obj) {
199 public void processPrimitiveList(String propName, Introspector obj) {
207 public void modifyComplexList(List<Introspector> list, List<Object> listReference, Introspector parent, Introspector child) {
213 * Builds the message.
215 * @param severity the severity
216 * @param error the error
217 * @param detail the detail
220 private Issue buildMessage(Severity severity, IssueType error, String detail) {
221 Issue message = new Issue();
222 message.setSeverity(severity);
223 message.setType(error);
224 message.setDetail(detail);
233 public boolean createComplexObjIfNull() {
241 public int createComplexListSize(Introspector parent, Introspector child) {
245 public static class Builder {
247 private boolean validateRequired = true;
248 private List<IssueResolver> issueResolvers = null;
249 private int maximumDepth = AAIProperties.MAXIMUM_DEPTH;
251 * Instantiates a new builder.
253 * @param llBuilder the ll builder
256 issueResolvers = new ArrayList<IssueResolver>();
262 * @param validateRequired the validate required
263 * @return the builder
265 public Builder validateRequired(boolean validateRequired) {
266 this.validateRequired = validateRequired;
270 public Builder restrictDepth(int depth) {
271 this.maximumDepth = depth;
277 * @param resolver the resolver
278 * @return the builder
280 public Builder addResolver(IssueResolver resolver) {
281 issueResolvers.add(resolver);
288 * @return the introspector validator
290 public IntrospectorValidator build() {
291 return new IntrospectorValidator(this);
295 * Gets the validate required.
297 * @return the validate required
299 public boolean getValidateRequired() {
300 return this.validateRequired;
304 * Gets the resolvers.
306 * @return the resolvers
308 public List<IssueResolver> getResolvers() {
309 return this.issueResolvers;
312 public int getMaximumDepth() {
313 return this.maximumDepth;