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 org.openecomp.aai.db.props.AAIProperties;
24 import org.openecomp.aai.exceptions.AAIException;
25 import org.openecomp.aai.introspection.Introspector;
26 import org.openecomp.aai.introspection.IntrospectorWalker;
27 import org.openecomp.aai.introspection.Visibility;
28 import org.openecomp.aai.introspection.Wanderer;
29 import org.openecomp.aai.schema.enums.PropertyMetadata;
33 public class IntrospectorValidator implements Wanderer {
36 private List<Issue> issues = null;
37 private List<IssueResolver> issueResolvers = null;
38 private boolean validateRequired = true;
39 private final int maximumDepth;
40 private int currentDepth = 0;
42 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");
68 * @return true, if successful
69 * @throws AAIException
71 public boolean validate(Introspector obj) throws AAIException {
72 IntrospectorWalker walker = new IntrospectorWalker(this);
73 this.currentDepth = 0;
76 for (Issue m : issues) {
77 if (!m.getSeverity().equals(Severity.WARNING)) {
90 public List<Issue> getIssues() {
95 * Sets the issue resolvers.
97 * @param resolvers the new issue resolvers
99 public void setIssueResolvers(List<IssueResolver> resolvers) {
100 issueResolvers = new ArrayList<>();
101 for (IssueResolver resolver : resolvers) {
102 issueResolvers.add(resolver);
109 * @return true, if successful
111 public boolean resolveIssues() {
112 boolean result = true;
113 for (Issue issue : issues) {
114 for (IssueResolver resolver : issueResolvers) {
115 if (resolver.resolveIssue(issue)) {
116 issue.setResolved(true);
119 if (!issue.isResolved()) {
131 public void processComplexObj(Introspector obj) {
133 if (this.currentDepth > this.maximumDepth && !relationshipChain.contains(obj.getDbName())) {
135 this.buildMessage(Severity.CRITICAL, IssueType.EXCEEDED_ALLOWED_DEPTH, "Maximum allowed depth of this object has been exceeded on: " + obj.getDbName());
136 message.setIntrospector(obj);
139 Set<String> requiredProps = obj.getRequiredProperties();
140 Set<String> keys = obj.getKeys();
141 Set<String> props = obj.getProperties();
143 for (String prop : props) {
144 Object value = obj.getValue(prop);
145 if (keys.contains(prop)) {
148 this.buildMessage(Severity.CRITICAL, IssueType.MISSING_KEY_PROP, "Missing key property: " + prop);
149 message.setIntrospector(obj);
150 message.setPropName(prop);
153 } else if (requiredProps.contains(prop)) {
154 if (value == null && validateRequired) {
156 this.buildMessage(Severity.CRITICAL, IssueType.MISSING_REQUIRED_PROP, "Missing required property: " + prop);
157 message.setIntrospector(obj);
158 message.setPropName(prop);
163 final Optional<String> visibility = obj.getPropertyMetadata(prop, PropertyMetadata.VISIBILITY);
164 if(visibility.isPresent() && Visibility.internal.equals(Visibility.valueOf(visibility.get())) && obj.getValue(prop) != null) {
166 this.buildMessage(Severity.ERROR, IssueType.PROPERTY_NOT_VISIBLE, "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)) {
175 this.buildMessage(Severity.CRITICAL, IssueType.DEPENDENT_PROP_NOT_FOUND, 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, 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;
252 * Instantiates a new builder.
254 * @param llBuilder the ll builder
257 issueResolvers = new ArrayList<IssueResolver>();
263 * @param validateRequired the validate required
264 * @return the builder
266 public Builder validateRequired(boolean validateRequired) {
267 this.validateRequired = validateRequired;
271 public Builder restrictDepth(int depth) {
272 this.maximumDepth = depth;
278 * @param resolver the resolver
279 * @return the builder
281 public Builder addResolver(IssueResolver resolver) {
282 issueResolvers.add(resolver);
289 * @return the introspector validator
291 public IntrospectorValidator build() {
292 return new IntrospectorValidator(this);
296 * Gets the validate required.
298 * @return the validate required
300 public boolean getValidateRequired() {
301 return this.validateRequired;
305 * Gets the resolvers.
307 * @return the resolvers
309 public List<IssueResolver> getResolvers() {
310 return this.issueResolvers;
313 public int getMaximumDepth() {
314 return this.maximumDepth;