Skip to content

Package: ViewBuilder

ViewBuilder

nameinstructionbranchcomplexitylinemethod
ViewBuilder(Class, Class)
M: 6 C: 85
93%
M: 11 C: 11
50%
M: 11 C: 1
8%
M: 0 C: 4
100%
M: 0 C: 1
100%
computeConstructorArguments(Site, Constructor, Object[])
M: 6 C: 75
93%
M: 1 C: 9
90%
M: 1 C: 5
83%
M: 1 C: 11
92%
M: 0 C: 1
100%
createViewAndController(Id, SiteNode)
M: 26 C: 59
69%
M: 4 C: 0
0%
M: 2 C: 1
33%
M: 6 C: 8
57%
M: 0 C: 1
100%
static {...}
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
toString()
M: 0 C: 6
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%

Coverage

1: /*
2: * #%L
3: * *********************************************************************************************************************
4: *
5: * NorthernWind - lightweight CMS
6: * http://northernwind.tidalwave.it - git clone https://bitbucket.org/tidalwave/northernwind-src.git
7: * %%
8: * Copyright (C) 2011 - 2023 Tidalwave s.a.s. (http://tidalwave.it)
9: * %%
10: * *********************************************************************************************************************
11: *
12: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
13: * the License. You may obtain a copy of the License at
14: *
15: * http://www.apache.org/licenses/LICENSE-2.0
16: *
17: * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
18: * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
19: * specific language governing permissions and limitations under the License.
20: *
21: * *********************************************************************************************************************
22: *
23: *
24: * *********************************************************************************************************************
25: * #L%
26: */
27: package it.tidalwave.northernwind.frontend.impl.ui;
28:
29: import java.lang.reflect.Constructor;
30: import java.lang.reflect.InvocationTargetException;
31: import javax.annotation.Nonnull;
32: import javax.inject.Inject;
33: import java.util.ArrayList;
34: import java.util.List;
35: import org.springframework.beans.factory.BeanCreationException;
36: import org.springframework.beans.factory.BeanFactory;
37: import org.springframework.beans.factory.annotation.Configurable;
38: import it.tidalwave.util.Id;
39: import it.tidalwave.northernwind.core.model.HttpStatusException;
40: import it.tidalwave.northernwind.core.model.Site;
41: import it.tidalwave.northernwind.core.model.SiteNode;
42: import it.tidalwave.northernwind.core.model.SiteProvider;
43: import it.tidalwave.northernwind.frontend.ui.ViewController;
44: import it.tidalwave.northernwind.frontend.ui.ViewFactory.ViewAndController;
45: import lombok.ToString;
46: import lombok.extern.slf4j.Slf4j;
47:
48: /***********************************************************************************************************************
49: *
50: * A builder which creates a View - ViewController pair.
51: *
52: * @stereotype Factory
53: *
54: * @author Fabrizio Giudici
55: *
56: **********************************************************************************************************************/
57: @Configurable @Slf4j @ToString(exclude = "beanFactory")
58: /* package */ class ViewBuilder
59: {
60: @Inject
61: private BeanFactory beanFactory;
62:
63: @Nonnull
64: /* package */ final Constructor<?> viewConstructor;
65:
66: @Nonnull
67: /* package */ final Constructor<? extends ViewController> viewControllerConstructor;
68:
69: /*******************************************************************************************************************
70: *
71: *
72: ******************************************************************************************************************/
73: public ViewBuilder (@Nonnull final Class<?> viewClass,
74: @Nonnull final Class<? extends ViewController> viewControllerClass)
75: throws
76: IllegalArgumentException, SecurityException
77:• {
78: viewConstructor = viewClass.getConstructors()[0];
79: viewControllerConstructor = (Constructor<ViewController>)viewControllerClass.getConstructors()[0];
80:• }
81:
82: /*******************************************************************************************************************
83: *
84: * Creates a new View - ViewController pair. They are first instantiated, and then dependency injection by means
85: * of constructor parameters occur. Injected fields are: the id, the {@link SiteNode}, any service declared in
86: * the Spring context, including {@link Site}; furthermore, a reference of the View is injected in the Controller.
87: *
88: * @param id the view id
89: * @param siteNode the {@link SiteNode} the view will be built for
90: * @return the created view
91: *
92: ******************************************************************************************************************/
93: @Nonnull
94: public ViewAndController createViewAndController (@Nonnull final Id id, @Nonnull final SiteNode siteNode)
95: throws HttpStatusException
96: {
97: log.debug("createViewAndController({}, {})", id, siteNode);
98:
99: try
100: {
101: final var site = siteNode.getSite();
102: final var view = viewConstructor.newInstance(
103: computeConstructorArguments(site, viewConstructor, id, siteNode));
104: final var controller = viewControllerConstructor.newInstance(
105: computeConstructorArguments(site, viewControllerConstructor, id, siteNode, view));
106: controller.initialize();
107: return new ViewAndController(view, controller);
108: }
109: catch (InvocationTargetException e)
110: {
111: // FIXME: cumbersome
112:• if ((e.getCause() instanceof BeanCreationException) && (e.getCause().getCause() instanceof HttpStatusException))
113: {
114: throw (HttpStatusException)e.getCause().getCause();
115: }
116:
117: throw new RuntimeException(e);
118: }
119: catch (Exception e)
120: {
121: throw new RuntimeException(e);
122: }
123: }
124:
125: /*******************************************************************************************************************
126: *
127: * Computes the argument values for calling the given constructor. They are taken from the current
128: * {@link BeanFactory}, with {@code overridingArgs} eventually overriding them.
129: *
130: * @param site the site
131: * @param constructor the constructor
132: * @param overridingArgs the overriding arguments
133: * @return the arguments to pass to the constructor
134: *
135: ******************************************************************************************************************/
136: @Nonnull
137: private Object[] computeConstructorArguments (@Nonnull final Site site,
138: @Nonnull final Constructor<?> constructor,
139: @Nonnull final Object ... overridingArgs)
140: {
141: final List<Object> result = new ArrayList<>();
142:
143:• x: for (final var argumentType : constructor.getParameterTypes())
144: {
145:• for (final var overridingArg : overridingArgs)
146: {
147:• if (argumentType.isAssignableFrom(overridingArg.getClass()))
148: {
149: result.add(overridingArg);
150: continue x;
151: }
152: }
153:
154:• if (Site.class.isAssignableFrom(argumentType))
155: {
156: result.add(beanFactory.getBean(SiteProvider.class).getSite());
157: }
158:• else if (BeanFactory.class.isAssignableFrom(argumentType))
159: {
160: result.add(beanFactory);
161: }
162: else
163: {
164: result.add(beanFactory.getBean(argumentType));
165: }
166: }
167:
168: return result.toArray();
169: }
170: }