001// -------------------------------------------------------------------------------- 002// Copyright 2002-2024 Echo Three, LLC 003// 004// Licensed under the Apache License, Version 2.0 (the "License"); 005// you may not use this file except in compliance with the License. 006// You may obtain a copy of the License at 007// 008// http://www.apache.org/licenses/LICENSE-2.0 009// 010// Unless required by applicable law or agreed to in writing, software 011// distributed under the License is distributed on an "AS IS" BASIS, 012// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013// See the License for the specific language governing permissions and 014// limitations under the License. 015// -------------------------------------------------------------------------------- 016 017package com.echothree.util.common.transfer; 018 019import com.echothree.model.control.core.common.transfer.EntityInstanceTransfer; 020import com.echothree.util.common.string.StringUtils; 021import com.echothree.util.common.transfer.BaseTransfer; 022import com.echothree.util.common.transfer.BaseWrapper; 023import java.lang.reflect.InvocationTargetException; 024import java.lang.reflect.Method; 025import java.util.Collection; 026import java.util.HashSet; 027import java.util.Set; 028import org.apache.commons.logging.Log; 029import org.apache.commons.logging.LogFactory; 030 031public class BaseTransferUtils { 032 033 private static Log log = LogFactory.getLog(BaseTransferUtils.class); 034 035 private BaseTransferUtils() { 036 super(); 037 } 038 039 private static class BaseTransferUtilsHolder { 040 static BaseTransferUtils instance = new BaseTransferUtils(); 041 } 042 043 public static BaseTransferUtils getInstance() { 044 return BaseTransferUtilsHolder.instance; 045 } 046 047 private void getEntityRefsFromBaseWrapper(EntityRefExclusions entityRefExclusions, Set<String> entityRefs, Set<Object> visitedObjects, 048 BaseWrapper<?> baseWrapper, int indentCount) { 049 Collection<?> collection = baseWrapper.getCollection(); 050 051 if(!collection.isEmpty()) { 052 collection.stream().filter((nextDependsOn) -> !visitedObjects.contains(nextDependsOn)).forEach((nextDependsOn) -> { 053 getEntityRefs(entityRefExclusions, entityRefs, visitedObjects, nextDependsOn, indentCount + 1); 054 }); 055 } 056 } 057 058 private Set<String> getEntityRefs(EntityRefExclusions entityRefExclusions, Set<String> entityRefs, Set<Object> visitedObjects, Object dependsOn, 059 int indentCount) { 060 if(BaseTransferUtilsDebugFlags.LogVisits) { 061 log.info(StringUtils.getInstance().getIndent(4, indentCount) + "Visiting " + dependsOn); 062 } 063 visitedObjects.add(dependsOn); 064 065 if(dependsOn instanceof BaseTransfer) { 066 EntityInstanceTransfer entityInstance = ((BaseTransfer)dependsOn).getEntityInstance(); 067 boolean includeMethods = true; 068 069 if(entityInstance != null) { 070 String nextDependsOnEntityRef = entityInstance.getEntityRef(); 071 072 if(nextDependsOnEntityRef != null) { 073 if(entityRefExclusions != null && nextDependsOnEntityRef != null && entityRefExclusions.contains(nextDependsOnEntityRef)) { 074 if(BaseTransferUtilsDebugFlags.LogGetEntityRefs) { 075 log.info(StringUtils.getInstance().getIndent(4, indentCount) + "Excluding " + nextDependsOnEntityRef); 076 } 077 078 includeMethods = false; 079 } else { 080 if(BaseTransferUtilsDebugFlags.LogGetEntityRefs) { 081 log.info(StringUtils.getInstance().getIndent(4, indentCount) + "Including " + nextDependsOnEntityRef); 082 } 083 084 entityRefs.add(nextDependsOnEntityRef); 085 } 086 } 087 } 088 089 if(includeMethods) { 090 Method[] methods = dependsOn.getClass().getMethods(); 091 092 for(var method : methods) { 093 String name = method.getName(); 094 095 if(name.startsWith("get")) { 096 try { 097 Class<?> returnType = method.getReturnType(); 098 099 if(BaseTransfer.class.isAssignableFrom(returnType)) { 100 // If it's a BaseTransfer... 101 BaseTransfer nextDependsOn = (BaseTransfer)method.invoke(dependsOn); 102 103 if(nextDependsOn != null) { 104 if(!visitedObjects.contains(nextDependsOn)) { 105 getEntityRefs(entityRefExclusions, entityRefs, visitedObjects, nextDependsOn, indentCount + 1); 106 } else { 107 if(BaseTransferUtilsDebugFlags.LogVisits) { 108 log.info(StringUtils.getInstance().getIndent(4, indentCount) + "Already visited " + nextDependsOn); 109 } 110 } 111 } 112 } else if(BaseWrapper.class.isAssignableFrom(returnType)) { 113 // If it's a BaseWrapper 114 BaseWrapper<?> baseWrapper = (BaseWrapper<?>)method.invoke(dependsOn); 115 116 if(baseWrapper != null) { 117 if(BaseTransferUtilsDebugFlags.LogGetEntityRefs) { 118 log.info(StringUtils.getInstance().getIndent(4, indentCount) + "BaseWrapper found: " + name.substring(3)); 119 } 120 121 getEntityRefsFromBaseWrapper(entityRefExclusions, entityRefs, visitedObjects, baseWrapper, indentCount); 122 } 123 } 124 } catch(IllegalAccessException iea) { 125 throw new RuntimeException(iea); 126 } catch(IllegalArgumentException iea) { 127 throw new RuntimeException(iea); 128 } catch(InvocationTargetException ite) { 129 throw new RuntimeException(ite); 130 } 131 } 132 } 133 } 134 } else if(dependsOn instanceof BaseWrapper) { 135 BaseWrapper<?> baseWrapper = (BaseWrapper<?>)dependsOn; 136 137 if(baseWrapper != null) { 138 if(BaseTransferUtilsDebugFlags.LogGetEntityRefs) { 139 log.info(StringUtils.getInstance().getIndent(4, indentCount) + "BaseWrapper passed in"); 140 } 141 142 getEntityRefsFromBaseWrapper(entityRefExclusions, entityRefs, visitedObjects, baseWrapper, indentCount); 143 } 144 } 145 146 return entityRefs; 147 } 148 149 public Set<String> getEntityRefs(EntityRefExclusions entityRefExclusions, Object object) { 150 Set<String> entityRefs = new HashSet<>(); 151 Set<Object> visitedObjects = new HashSet<>(); 152 153 if(BaseTransferUtilsDebugFlags.LogGetEntityRefs) { 154 log.info("Starting getEntityRefs for " + object); 155 } 156 157 if(object instanceof BaseTransfer || object instanceof BaseWrapper) { 158 getEntityRefs(entityRefExclusions, entityRefs, visitedObjects, object, 1); 159 } else { 160 throw new IllegalArgumentException("Object for getEntityRefs(...) must be a BaseTransfer or BaseWrapper object."); 161 } 162 163 if(BaseTransferUtilsDebugFlags.LogGetEntityRefs) { 164 log.info("Ending getEntityRefs"); 165 } 166 167 return entityRefs; 168 } 169 170}