1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.ui.framework.ioc;
35
36 import info.magnolia.objectfactory.ParameterInfo;
37 import info.magnolia.objectfactory.ParameterResolver;
38 import info.magnolia.ui.framework.ContextProperty;
39 import info.magnolia.ui.framework.LeakagePreventingWrapper;
40 import info.magnolia.ui.framework.UiFrameworkView;
41 import info.magnolia.ui.framework.ViewContext;
42 import info.magnolia.ui.framework.ViewContextBase;
43 import info.magnolia.ui.framework.ViewContextProxy;
44
45 import java.util.Arrays;
46 import java.util.Map;
47 import java.util.Objects;
48 import java.util.Optional;
49 import java.util.stream.Collectors;
50
51 import javax.inject.Provider;
52
53
54
55
56
57
58
59
60
61
62
63
64
65 class ViewContextParameterResolver implements ParameterResolver {
66
67 private final static Class[] BLACK_LIST = new Class[] { Provider.class, com.google.inject.Provider.class };
68
69 private final UiContextReference uiContextReference;
70
71 ViewContextParameterResolver(UiContextReference uiContextReference) {
72 this.uiContextReference = uiContextReference;
73 }
74
75 @Override
76 @SuppressWarnings("unchecked")
77 public Object resolveParameter(ParameterInfo parameter) {
78 final Class<?> parameterType = parameter.getParameterType();
79
80
81
82
83
84 boolean isBlackListed = Arrays.stream(BLACK_LIST).anyMatch(blackListedType -> blackListedType.isAssignableFrom(parameterType));
85 if (isBlackListed) {
86 return ParameterResolver.UNRESOLVED;
87 }
88
89 return lookup(parameterType);
90 }
91
92 private Object lookup(Class<?> parameterType) {
93 final BeanStore beanStore = SessionStore.access().getBeanStore(uiContextReference);
94 final Optional<Object> valueFromCurrentStore = Optional.ofNullable(beanStore.getClosestInstance(parameterType));
95
96 final Object param = valueFromCurrentStore.orElseGet(() -> uiContextReference.getParentReferences().stream()
97 .map(parentRef -> SessionStore.access().getBeanStore(parentRef))
98 .map(parentStore -> parentStore.getClosestInstance(parameterType))
99 .filter(Objects::nonNull)
100 .findFirst()
101 .map(parameter -> parameter instanceof ViewContext ? wrapViewContext((ViewContext) parameter) : parameter)
102 .orElse(ParameterResolver.UNRESOLVED));
103
104 if ((param instanceof ViewContext) && !valueFromCurrentStore.isPresent()) {
105 final ViewContext wrappedViewContext = wrapViewContext((ViewContext) param);
106 beanStore.put(parameterType, wrappedViewContext);
107 return wrappedViewContext;
108 }
109
110 return param;
111 }
112
113 private ViewContext wrapViewContext(ViewContext viewContext) {
114 final ViewContextBase baseViewContext = (ViewContextBase) viewContext;
115 final Map<String, ContextProperty> properties = baseViewContext.properties();
116 final Map<String, ContextProperty> wrappedProperties =
117 properties.entrySet()
118 .stream()
119 .collect(Collectors.toMap(Map.Entry::getKey, entry -> {
120 final ContextProperty<?> contextProperty = entry.getValue();
121 return new LeakagePreventingWrapper<>(contextProperty);
122 }));
123
124 return new ViewContextProxy().createViewContext(baseViewContext.getViewContextType(), wrappedProperties);
125 }
126 }