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