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;
23 import java.util.HashSet;
24 import java.util.LinkedHashSet;
25 import java.util.List;
28 import org.openecomp.aai.exceptions.AAIException;
29 import org.openecomp.aai.introspection.exceptions.AAIUnknownObjectException;
30 import com.att.eelf.configuration.EELFLogger;
31 import com.att.eelf.configuration.EELFManager;
33 public class IntrospectorWalker {
35 private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(IntrospectorWalker.class);
37 private Wanderer w = null;
38 private Set<String> blacklist = null;
39 private boolean preventCycles = false;
40 private final PropertyPredicate<Introspector, String> propVisibility;
43 * Instantiates a new introspector walker.
46 * @param llBuilder the ll builder
48 public IntrospectorWalker(Wanderer w) {
50 this.blacklist = new HashSet<>();
51 this.propVisibility = null;
54 public IntrospectorWalker(Wanderer w, PropertyPredicate<Introspector, String> p) {
56 this.blacklist = new HashSet<>();
57 this.propVisibility = p;
64 * @param list the new blacklist
66 public void setBlacklist(List<String> list) {
67 blacklist.addAll(list);
73 * @param prevent the prevent
75 public void preventCycles(boolean prevent) {
76 this.preventCycles = prevent;
83 * @throws AAIException
85 public void walk(Introspector obj) throws AAIException {
86 Set<String> visited = new HashSet<>();
88 walk(obj, null, visited);
95 * @param parent the parent
96 * @throws AAIException
98 private void walk(Introspector obj, Introspector parent, Set<String> visited) throws AAIException {
99 boolean stopRecursion = false;
100 Set<String> localVisited = new HashSet<>();
101 localVisited.addAll(visited);
103 if (visited.contains(obj.getName())) {
104 stopRecursion = true;
106 if (!obj.isContainer()) {
107 localVisited.add(obj.getName()); //so we don't recurse while walking its children
111 //props must duplicate the result from getProperties because
113 if (this.propVisibility == null) {
114 props = new LinkedHashSet<>(obj.getProperties());
116 props = new LinkedHashSet<>(obj.getProperties(this.propVisibility));
119 w.processComplexObj(obj);
120 props.removeAll(blacklist);
121 if (!obj.isContainer()) {
124 for (String prop : props) {
126 if (obj.isSimpleType(prop)) {
128 w.processPrimitive(prop, obj);
129 } else if (obj.isListType(prop) && !stopRecursion) {
131 List<Object> listReference = obj.getValue(prop);
132 boolean isComplexType = obj.isComplexGenericType(prop);
134 List<Introspector> list = obj.getWrappedListValue(prop);
136 Introspector child = obj.newIntrospectorInstanceOfNestedProperty(prop);
137 w.modifyComplexList(list, listReference, parent, child);
138 for (Object item : listReference) {
139 child = IntrospectorFactory.newInstance(obj.getModelType(), item);
140 walk(child, parent, localVisited);
142 } catch (AAIUnknownObjectException e) {
143 LOGGER.warn("Skipping property " + prop + " (Unknown Object)", e);
146 w.processPrimitiveList(prop, obj);
148 if (listReference.size() == 0) {
151 Introspector child = obj.newIntrospectorInstanceOfNestedProperty(prop);
152 int size = w.createComplexListSize(parent, child);
153 for (int i = 0; i < size; i++) {
154 child = obj.newIntrospectorInstanceOfNestedProperty(prop);
155 walk(child, parent, localVisited);
156 listReference.add(child.getUnderlyingObject());
159 obj.setValue(prop, listReference);
160 } catch (AAIUnknownObjectException e) {
161 LOGGER.warn("Skipping property " + prop + " (Unknown Object)", e);
163 } else if (!isComplexType){
164 w.processPrimitiveList(prop, obj);
168 } else if (obj.isComplexType(prop) && !stopRecursion) {
169 Introspector child = null;
170 if (obj.getValue(prop) != null) {
171 child = IntrospectorFactory.newInstance(obj.getModelType(), obj.getValue(prop));
173 if (w.createComplexObjIfNull()) {
175 child = obj.newIntrospectorInstanceOfProperty(prop);
176 obj.setValue(prop, child.getUnderlyingObject());
177 } catch (AAIUnknownObjectException e) {
178 LOGGER.warn("Skipping property " + prop + " (Unknown Object)", e);
183 walk(child, obj, localVisited);
189 if (preventCycles && !obj.isContainer()) {
190 visited.remove(obj.getName()); //so we can see it down another path that isn't in danger of recursing over it