Skip to content

Package: AbstractRenderer

AbstractRenderer

nameinstructionbranchcomplexitylinemethod
AbstractRenderer(VElement, ViewModelContext, ReportService)
M: 5 C: 31
86%
M: 1 C: 5
83%
M: 1 C: 3
75%
M: 1 C: 11
92%
M: 0 C: 1
100%
checkRenderer()
M: 0 C: 9
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
dispose()
M: 0 C: 15
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
getRenderer(VElement, ViewModelContext)
M: 2 C: 20
91%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 1 C: 5
83%
M: 0 C: 1
100%
getReportService()
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
getVElement()
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
getViewModelContext()
M: 0 C: 5
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
lambda$0(Adapter)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
register(VElement)
M: 0 C: 14
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2011-2019 EclipseSource Muenchen GmbH and others.
3: *
4: * All rights reserved. This program and the accompanying materials
5: * are made available under the terms of the Eclipse Public License 2.0
6: * which accompanies this distribution, and is available at
7: * https://www.eclipse.org/legal/epl-2.0/
8: *
9: * SPDX-License-Identifier: EPL-2.0
10: *
11: * Contributors:
12: * Eugen - initial API and implementation
13: * Christian W. Damus - bug 548592
14: ******************************************************************************/
15: package org.eclipse.emf.ecp.view.model.common;
16:
17: import org.eclipse.emf.common.notify.Adapter;
18: import org.eclipse.emf.common.notify.impl.AdapterImpl;
19: import org.eclipse.emf.common.util.EList;
20: import org.eclipse.emf.ecore.util.EcoreUtil;
21: import org.eclipse.emf.ecp.view.spi.context.ViewModelContext;
22: import org.eclipse.emf.ecp.view.spi.model.VElement;
23: import org.eclipse.emfforms.spi.common.report.ReportService;
24:
25: /**
26: * Common super class for renderer.
27: *
28: * @author Eugen Neufeld
29: * @param <VELEMENT> the {@link VElement} this renderer is applicable for
30: *
31: */
32: public abstract class AbstractRenderer<VELEMENT extends VElement> {
33:
34:         private final VELEMENT vElement;
35:         private final ViewModelContext viewModelContext;
36:         private boolean disposed;
37:         private final ReportService reportService;
38:
39:         /**
40:          * Default constructor.
41:          *
42:          * @param vElement the {@link VElement} to be rendered
43:          * @param viewContext the {@link ViewModelContext} to use
44:          * @param reportService The {@link ReportService} to use
45:          * @since 1.6
46:          */
47:         public AbstractRenderer(final VELEMENT vElement, final ViewModelContext viewContext, ReportService reportService) {
48:
49:•                if (vElement == null) {
50:                         throw new IllegalArgumentException("vElement must not be null"); //$NON-NLS-1$
51:                 }
52:•                if (viewContext == null) {
53:                         throw new IllegalArgumentException("vContext must not be null"); //$NON-NLS-1$
54:                 }
55:•                if (reportService == null) {
56:                         throw new IllegalArgumentException("reportService must not be null"); //$NON-NLS-1$
57:                 }
58:                 this.vElement = vElement;
59:                 this.viewModelContext = viewContext;
60:                 this.reportService = reportService;
61:
62:                 register(vElement);
63:         }
64:
65:         /**
66:          * The {@link ViewModelContext} to use.
67:          *
68:          * @return the {@link ViewModelContext}
69:          */
70:         public final ViewModelContext getViewModelContext() {
71:                 checkRenderer();
72:                 return viewModelContext;
73:         }
74:
75:         /**
76:          * The {@link VElement} instance to use.
77:          *
78:          * @return the {@link VElement}
79:          */
80:         public final VELEMENT getVElement() {
81:                 checkRenderer();
82:                 return vElement;
83:         }
84:
85:         /**
86:          * Disposes all resources used by the renderer.
87:          * Don't forget to call super.dispose if overwriting this method.
88:          */
89:         protected void dispose() {
90:                 disposed = true;
91:
92:                 // JUnit tests often mock view-model elements, so there may not be an adapter list
93:                 final EList<Adapter> adapters = vElement.eAdapters();
94:•                if (adapters != null) {
95:                         adapters.removeIf(a -> a.isAdapterForType(this));
96:                 }
97:         }
98:
99:         /**
100:          * Checks whether the renderer is disposed and if so throws an {@link IllegalStateException}.
101:          *
102:          * @since 1.6
103:          */
104:         protected void checkRenderer() {
105:•                if (disposed) {
106:                         throw new IllegalStateException("Renderer is disposed"); //$NON-NLS-1$
107:                 }
108:
109:         }
110:
111:         /**
112:          * The {@link SWTRendererFactory} instance to use.
113:          *
114:          * @return the {@link SWTRendererFactory}
115:          * @since 1.6
116:          */
117:         protected final ReportService getReportService() {
118:                 checkRenderer();
119:                 return reportService;
120:         }
121:
122:         /**
123:          * Associate me with a view model element as its renderer. Multiple view-model elements
124:          * may be associated with one renderer.
125:          *
126:          * @param viewModelElement the view model element to register as rendered by me
127:          *
128:          * @since 1.22
129:          */
130:         protected void register(VElement viewModelElement) {
131:                 // JUnit tests often mock view-model elements, so there may not be an adapter list
132:                 final EList<Adapter> adapters = viewModelElement.eAdapters();
133:•                if (adapters != null) {
134:                         viewModelElement.eAdapters().add(new RendererAdapter());
135:                 }
136:         }
137:
138:         /**
139:          * Query the renderer that renders a given view model {@code element} in a particular
140:          * view model {@code context}.
141:          *
142:          * @param element a view model element rendered in some {@code context}
143:          * @param context the view model rendering {@code context}
144:          * @return the renderer, or {@code null} if the {@code element} is not rendered in this {@code context}
145:          *
146:          * @since 1.22
147:          */
148:         public static AbstractRenderer<? extends VElement> getRenderer(VElement element, ViewModelContext context) {
149:                 // JUnit tests often mock view-model elements, so there may not be an adapter list
150:                 final EList<Adapter> adapters = element.eAdapters();
151:•                if (adapters == null) {
152:                         return null;
153:                 }
154:
155:                 @SuppressWarnings("unchecked")
156:                 final AbstractRenderer<? extends VElement>.RendererAdapter adapter = (AbstractRenderer<? extends VElement>.RendererAdapter) EcoreUtil
157:                         .getAdapter(adapters, new ContextKey(context));
158:•                return adapter != null ? adapter.getRenderer() : null;
159:         }
160:
161:         //
162:         // Nested types
163:         //
164:
165:         /**
166:          * Adapter that associates a view model element with the renderer that renders it.
167:          *
168:          * @since 1.22
169:          */
170:         private final class RendererAdapter extends AdapterImpl {
171:
172:                 RendererAdapter() {
173:                         super();
174:                 }
175:
176:                 @Override
177:                 public boolean isAdapterForType(Object type) {
178:                         return type == AbstractRenderer.class
179:                                 || type == AbstractRenderer.this
180:                                 || type instanceof Class<?> && ((Class<?>) type).isInstance(AbstractRenderer.this)
181:                                 || type instanceof ContextKey && ((ContextKey) type).hasContext(getViewModelContext());
182:                 }
183:
184:                 AbstractRenderer<? extends VElement> getRenderer() {
185:                         return AbstractRenderer.this;
186:                 }
187:
188:         }
189:
190:         /**
191:          * A wrapper for the view model context used as a recognized type for the
192:          * renderer adapter that cannot be confused with any other adapter that uses
193:          * a view model context as its type.
194:          *
195:          * @since 1.22
196:          */
197:         private static final class ContextKey {
198:                 private final ViewModelContext context;
199:
200:                 ContextKey(ViewModelContext context) {
201:                         super();
202:
203:                         this.context = context;
204:                 }
205:
206:                 boolean hasContext(ViewModelContext context) {
207:                         return isInContext(this.context, context);
208:                 }
209:
210:                 /**
211:                  * Is a {@code context} either a child of or the same as a {@code parent} context?
212:                  *
213:                  * @param parent a possible parent context
214:                  * @param context a possible child context
215:                  * @return {@code true} if the {@code context} is or is, recursively, a child of the
216:                  * {@code parent}; {@code false}, otherwise
217:                  */
218:                 private boolean isInContext(ViewModelContext parent, ViewModelContext context) {
219:                         return parent == context
220:                                 || context.getParentContext() != null && isInContext(parent, context.getParentContext());
221:                 }
222:         }
223:
224: }