2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright © 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=========================================================
20 * ECOMP is a trademark and service mark of AT&T Intellectual Property.
22 package org.onap.aai.introspection.tools;
24 import org.onap.aai.db.props.AAIProperties;
25 import org.onap.aai.exceptions.AAIException;
26 import org.onap.aai.introspection.Introspector;
27 import org.onap.aai.introspection.IntrospectorWalker;
28 import org.onap.aai.introspection.Visibility;
29 import org.onap.aai.introspection.Wanderer;
30 import org.onap.aai.schema.enums.PropertyMetadata;
34 public class IntrospectorValidator implements Wanderer {
37 private List<Issue> issues = null;
38 private List<IssueResolver> issueResolvers = null;
39 private boolean validateRequired = true;
40 private final int maximumDepth;
41 private int currentDepth = 0;
43 private final Set<String> relationshipChain;
45 * Instantiates a new introspector validator.
47 * @param builder the builder
49 private IntrospectorValidator(Builder builder) {
50 this.validateRequired = builder.getValidateRequired();
51 this.issueResolvers = builder.getResolvers();
52 this.maximumDepth = builder.getMaximumDepth();
53 issues = new ArrayList<>();
55 relationshipChain = new HashSet<>();
57 relationshipChain.add("relationship-list");
58 relationshipChain.add("relationship");
59 relationshipChain.add("relationship-data");
60 relationshipChain.add("related-to-property");
69 * @return true, if successful
70 * @throws AAIException
72 public boolean validate(Introspector obj) throws AAIException {
73 IntrospectorWalker walker = new IntrospectorWalker(this);
74 this.currentDepth = 0;
77 for (Issue m : issues) {
78 if (!m.getSeverity().equals(Severity.WARNING)) {
91 public List<Issue> getIssues() {
96 * Sets the issue resolvers.
98 * @param resolvers the new issue resolvers
100 public void setIssueResolvers(List<IssueResolver> resolvers) {
101 issueResolvers = new ArrayList<>();
102 for (IssueResolver resolver : resolvers) {
103 issueResolvers.add(resolver);
110 * @return true, if successful
112 public boolean resolveIssues() {
113 boolean result = true;
114 for (Issue issue : issues) {
115 for (IssueResolver resolver : issueResolvers) {
116 if (resolver.resolveIssue(issue)) {
117 issue.setResolved(true);
120 if (!issue.isResolved()) {
132 public void processComplexObj(Introspector obj) {
134 if (this.currentDepth > this.maximumDepth && !relationshipChain.contains(obj.getDbName())) {
136 this.buildMessage(Severity.CRITICAL, IssueType.EXCEEDED_ALLOWED_DEPTH, "Maximum allowed depth of this object has been exceeded on: " + obj.getDbName());
137 message.setIntrospector(obj);
140 Set<String> requiredProps = obj.getRequiredProperties();
141 Set<String> keys = obj.getKeys();
142 Set<String> props = obj.getProperties();
144 for (String prop : props) {
145 Object value = obj.getValue(prop);
146 if (keys.contains(prop)) {
149 this.buildMessage(Severity.CRITICAL, IssueType.MISSING_KEY_PROP, "Missing key property: " + prop);
150 message.setIntrospector(obj);
151 message.setPropName(prop);
154 } else if (requiredProps.contains(prop)) {
155 if (value == null && validateRequired) {
157 this.buildMessage(Severity.CRITICAL, IssueType.MISSING_REQUIRED_PROP, "Missing required property: " + prop);
158 message.setIntrospector(obj);
159 message.setPropName(prop);
164 final Optional<String> visibility = obj.getPropertyMetadata(prop, PropertyMetadata.VISIBILITY);
165 if(visibility.isPresent() && Visibility.internal.equals(Visibility.valueOf(visibility.get())) && obj.getValue(prop) != null) {
167 this.buildMessage(Severity.ERROR, IssueType.PROPERTY_NOT_VISIBLE, "client attemptted to set property not visible: " + prop);
168 message.setIntrospector(obj);
169 message.setPropName(prop);
173 final Optional<String> requires = obj.getPropertyMetadata(prop, PropertyMetadata.REQUIRES);
174 if (requires.isPresent() && (obj.getValue(prop) != null && obj.getValue(requires.get()) == null)) {
176 this.buildMessage(Severity.CRITICAL, IssueType.DEPENDENT_PROP_NOT_FOUND, prop + " requires " + requires.get() + " to also be popluated.");
177 message.setIntrospector(obj);
178 message.setPropName(prop);
183 if (!relationshipChain.contains(obj.getDbName())) {
193 public void processPrimitive(String propName, Introspector obj) {
201 public void processPrimitiveList(String propName, Introspector obj) {
209 public void modifyComplexList(List<Introspector> list, List<Object> listReference, Introspector parent, Introspector child) {
215 * Builds the message.
217 * @param severity the severity
218 * @param error the error
219 * @param detail the detail
222 private Issue buildMessage(Severity severity, IssueType error, String detail) {
223 Issue message = new Issue();
224 message.setSeverity(severity);
225 message.setType(error);
226 message.setDetail(detail);
235 public boolean createComplexObjIfNull() {
243 public int createComplexListSize(Introspector parent, Introspector child) {
247 public static class Builder {
249 private boolean validateRequired = true;
250 private List<IssueResolver> issueResolvers = null;
251 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;
279 * @param resolver the resolver
280 * @return the builder
282 public Builder addResolver(IssueResolver resolver) {
283 issueResolvers.add(resolver);
290 * @return the introspector validator
292 public IntrospectorValidator build() {
293 return new IntrospectorValidator(this);
297 * Gets the validate required.
299 * @return the validate required
301 public boolean getValidateRequired() {
302 return this.validateRequired;
306 * Gets the resolvers.
308 * @return the resolvers
310 public List<IssueResolver> getResolvers() {
311 return this.issueResolvers;
314 public int getMaximumDepth() {
315 return this.maximumDepth;