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=========================================================
21 package org.onap.aai.introspection.tools;
25 import org.onap.aai.db.props.AAIProperties;
26 import org.onap.aai.exceptions.AAIException;
27 import org.onap.aai.introspection.Introspector;
28 import org.onap.aai.introspection.IntrospectorWalker;
29 import org.onap.aai.introspection.Visibility;
30 import org.onap.aai.introspection.Wanderer;
31 import org.onap.aai.schema.enums.PropertyMetadata;
33 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;
44 * Instantiates a new introspector validator.
46 * @param builder the builder
48 private IntrospectorValidator(Builder builder) {
49 this.validateRequired = builder.getValidateRequired();
50 this.issueResolvers = builder.getResolvers();
51 this.maximumDepth = builder.getMaximumDepth();
52 issues = new ArrayList<>();
54 relationshipChain = new HashSet<>();
56 relationshipChain.add("relationship-list");
57 relationshipChain.add("relationship");
58 relationshipChain.add("relationship-data");
59 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())) {
133 Issue message = this.buildMessage(Severity.CRITICAL, IssueType.EXCEEDED_ALLOWED_DEPTH,
134 "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)) {
146 Issue message = this.buildMessage(Severity.CRITICAL, IssueType.MISSING_KEY_PROP,
147 "Missing key property: " + prop);
148 message.setIntrospector(obj);
149 message.setPropName(prop);
152 } else if (requiredProps.contains(prop)) {
153 if (value == null && validateRequired) {
154 Issue message = this.buildMessage(Severity.CRITICAL, IssueType.MISSING_REQUIRED_PROP,
155 "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()))
164 && obj.getValue(prop) != null) {
165 Issue message = this.buildMessage(Severity.ERROR, IssueType.PROPERTY_NOT_VISIBLE,
166 "client attemptted to set property not visible: " + prop);
167 message.setIntrospector(obj);
168 message.setPropName(prop);
172 final Optional<String> requires = obj.getPropertyMetadata(prop, PropertyMetadata.REQUIRES);
173 if (requires.isPresent() && (obj.getValue(prop) != null && obj.getValue(requires.get()) == null)) {
174 Issue message = this.buildMessage(Severity.CRITICAL, IssueType.DEPENDENT_PROP_NOT_FOUND,
175 prop + " requires " + requires.get() + " to also be popluated.");
176 message.setIntrospector(obj);
177 message.setPropName(prop);
182 if (!relationshipChain.contains(obj.getDbName())) {
192 public void processPrimitive(String propName, Introspector obj) {
200 public void processPrimitiveList(String propName, Introspector obj) {
208 public void modifyComplexList(List<Introspector> list, List<Object> listReference, Introspector parent,
209 Introspector child) {
214 * Builds the message.
216 * @param severity the severity
217 * @param error the error
218 * @param detail the detail
221 private Issue buildMessage(Severity severity, IssueType error, String detail) {
222 Issue message = new Issue();
223 message.setSeverity(severity);
224 message.setType(error);
225 message.setDetail(detail);
234 public boolean createComplexObjIfNull() {
242 public int createComplexListSize(Introspector parent, Introspector child) {
246 public static class Builder {
248 private boolean validateRequired = true;
249 private List<IssueResolver> issueResolvers = null;
250 private int maximumDepth = AAIProperties.MAXIMUM_DEPTH;
253 * Instantiates a new builder.
255 * @param llBuilder the ll builder
258 issueResolvers = new ArrayList<IssueResolver>();
264 * @param validateRequired the validate required
265 * @return the builder
267 public Builder validateRequired(boolean validateRequired) {
268 this.validateRequired = validateRequired;
272 public Builder restrictDepth(int depth) {
273 this.maximumDepth = depth;
280 * @param resolver the resolver
281 * @return the builder
283 public Builder addResolver(IssueResolver resolver) {
284 issueResolvers.add(resolver);
291 * @return the introspector validator
293 public IntrospectorValidator build() {
294 return new IntrospectorValidator(this);
298 * Gets the validate required.
300 * @return the validate required
302 public boolean getValidateRequired() {
303 return this.validateRequired;
307 * Gets the resolvers.
309 * @return the resolvers
311 public List<IssueResolver> getResolvers() {
312 return this.issueResolvers;
315 public int getMaximumDepth() {
316 return this.maximumDepth;