2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 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.openecomp.aai.introspection.tools;
23 import java.util.ArrayList;
24 import java.util.HashSet;
25 import java.util.List;
26 import java.util.Optional;
29 import org.openecomp.aai.db.props.AAIProperties;
30 import org.openecomp.aai.exceptions.AAIException;
31 import org.openecomp.aai.introspection.Introspector;
32 import org.openecomp.aai.introspection.IntrospectorWalker;
33 import org.openecomp.aai.introspection.Visibility;
34 import org.openecomp.aai.introspection.Wanderer;
35 import org.openecomp.aai.schema.enums.PropertyMetadata;
37 public class IntrospectorValidator implements Wanderer {
40 private List<Issue> issues = null;
41 private List<IssueResolver> issueResolvers = null;
42 private boolean validateRequired = true;
43 private final int maximumDepth;
44 private int currentDepth = 0;
46 private final Set<String> relationshipChain;
48 * Instantiates a new introspector validator.
50 * @param builder the builder
52 private IntrospectorValidator(IntrospectorValidator.Builder builder) {
53 this.validateRequired = builder.getValidateRequired();
54 this.issueResolvers = builder.getResolvers();
55 this.maximumDepth = builder.getMaximumDepth();
56 issues = new ArrayList<>();
58 relationshipChain = new HashSet<>();
60 relationshipChain.add("relationship-list");
61 relationshipChain.add("relationship");
62 relationshipChain.add("relationship-data");
63 relationshipChain.add("related-to-property");
72 * @return true, if successful
73 * @throws AAIException
75 public boolean validate(Introspector obj) throws AAIException {
76 IntrospectorWalker walker = new IntrospectorWalker(this);
77 this.currentDepth = 0;
80 for (Issue m : issues) {
81 if (!m.getSeverity().equals(Severity.WARNING)) {
94 public List<Issue> getIssues() {
99 * Sets the issue resolvers.
101 * @param resolvers the new issue resolvers
103 public void setIssueResolvers(List<IssueResolver> resolvers) {
104 issueResolvers = new ArrayList<>();
105 for (IssueResolver resolver : resolvers) {
106 issueResolvers.add(resolver);
113 * @return true, if successful
115 public boolean resolveIssues() {
116 boolean result = true;
117 for (Issue issue : issues) {
118 for (IssueResolver resolver : issueResolvers) {
119 if (resolver.resolveIssue(issue)) {
120 issue.setResolved(true);
123 if (!issue.isResolved()) {
135 public void processComplexObj(Introspector obj) {
137 if (this.currentDepth > this.maximumDepth && !relationshipChain.contains(obj.getDbName())) {
139 this.buildMessage(Severity.CRITICAL, IssueType.EXCEEDED_ALLOWED_DEPTH, "Maximum allowed depth of this object has been exceeded on: " + obj.getDbName());
140 message.setIntrospector(obj);
143 Set<String> requiredProps = obj.getRequiredProperties();
144 Set<String> keys = obj.getKeys();
145 Set<String> props = obj.getProperties();
147 for (String prop : props) {
148 Object value = obj.getValue(prop);
149 if (keys.contains(prop)) {
152 this.buildMessage(Severity.CRITICAL, IssueType.MISSING_KEY_PROP, "Missing key property: " + prop);
153 message.setIntrospector(obj);
154 message.setPropName(prop);
157 } else if (requiredProps.contains(prop)) {
158 if (value == null && validateRequired) {
160 this.buildMessage(Severity.CRITICAL, IssueType.MISSING_REQUIRED_PROP, "Missing required property: " + prop);
161 message.setIntrospector(obj);
162 message.setPropName(prop);
167 final Optional<String> visibility = obj.getPropertyMetadata(prop, PropertyMetadata.VISIBILITY);
168 if(visibility.isPresent() && Visibility.internal.equals(Visibility.valueOf(visibility.get())) && obj.getValue(prop) != null) {
170 this.buildMessage(Severity.ERROR, IssueType.PROPERTY_NOT_VISIBLE, "client attemptted to set property not visible: " + prop);
171 message.setIntrospector(obj);
172 message.setPropName(prop);
176 final Optional<String> requires = obj.getPropertyMetadata(prop, PropertyMetadata.REQUIRES);
177 if (requires.isPresent() && (obj.getValue(prop) != null && obj.getValue(requires.get()) == null)) {
179 this.buildMessage(Severity.CRITICAL, IssueType.DEPENDENT_PROP_NOT_FOUND, prop + " requires " + requires.get() + " to also be popluated.");
180 message.setIntrospector(obj);
181 message.setPropName(prop);
186 if (!relationshipChain.contains(obj.getDbName())) {
196 public void processPrimitive(String propName, Introspector obj) {
204 public void processPrimitiveList(String propName, Introspector obj) {
212 public void modifyComplexList(List<Introspector> list, List<Object> listReference, Introspector parent, Introspector child) {
218 * Builds the message.
220 * @param severity the severity
221 * @param error the error
222 * @param detail the detail
225 private Issue buildMessage(Severity severity, IssueType error, String detail) {
226 Issue message = new Issue();
227 message.setSeverity(severity);
228 message.setType(error);
229 message.setDetail(detail);
238 public boolean createComplexObjIfNull() {
246 public int createComplexListSize(Introspector parent, Introspector child) {
250 public static class Builder {
252 private boolean validateRequired = true;
253 private List<IssueResolver> issueResolvers = null;
254 private int maximumDepth = AAIProperties.MAXIMUM_DEPTH;
256 * Instantiates a new builder.
258 * @param llBuilder the ll builder
261 issueResolvers = new ArrayList<IssueResolver>();
267 * @param validateRequired the validate required
268 * @return the builder
270 public Builder validateRequired(boolean validateRequired) {
271 this.validateRequired = validateRequired;
275 public Builder restrictDepth(int depth) {
276 this.maximumDepth = depth;
282 * @param resolver the resolver
283 * @return the builder
285 public Builder addResolver(IssueResolver resolver) {
286 issueResolvers.add(resolver);
293 * @return the introspector validator
295 public IntrospectorValidator build() {
296 return new IntrospectorValidator(this);
300 * Gets the validate required.
302 * @return the validate required
304 public boolean getValidateRequired() {
305 return this.validateRequired;
309 * Gets the resolvers.
311 * @return the resolvers
313 public List<IssueResolver> getResolvers() {
314 return this.issueResolvers;
317 public int getMaximumDepth() {
318 return this.maximumDepth;