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