Skip to content

Package: SelectionTableCompositeStrategyProvider

SelectionTableCompositeStrategyProvider

nameinstructionbranchcomplexitylinemethod
SelectionTableCompositeStrategyProvider()
M: 0 C: 8
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
create(EObject, EReference)
M: 0 C: 23
100%
M: 1 C: 1
50%
M: 1 C: 1
50%
M: 0 C: 7
100%
M: 0 C: 1
100%
findTableControl(VView, EObject, EStructuralFeature)
M: 9 C: 95
91%
M: 11 C: 13
54%
M: 10 C: 3
23%
M: 2 C: 25
93%
M: 0 C: 1
100%
getLoadingProperties(EObject, EStructuralFeature)
M: 0 C: 11
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 3
100%
M: 0 C: 1
100%
getTableControl(EObject, EStructuralFeature)
M: 0 C: 23
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 6
100%
M: 0 C: 1
100%
getTableControl(UniqueSetting)
M: 0 C: 17
100%
M: 0 C: 2
100%
M: 0 C: 2
100%
M: 0 C: 4
100%
M: 0 C: 1
100%
lambda$0(VTableControl, EObject, EReference, Collection)
M: 0 C: 8
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
provides(EObject, EReference)
M: 0 C: 22
100%
M: 0 C: 4
100%
M: 0 C: 3
100%
M: 0 C: 5
100%
M: 0 C: 1
100%
resolvesTo(VDomainModelReference, EObject, EStructuralFeature)
M: 2 C: 20
91%
M: 2 C: 2
50%
M: 2 C: 1
33%
M: 0 C: 5
100%
M: 0 C: 1
100%
setDatabinding(EMFFormsDatabindingEMF)
M: 0 C: 4
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
static {...}
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%
strategy(VTableControl)
M: 0 C: 3
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 1
100%
M: 0 C: 1
100%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2019 Christian W. Damus 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: * Christian W. Damus - initial API and implementation
13: ******************************************************************************/
14: package org.eclipse.emfforms.swt.internal.reference.table;
15:
16: import static java.util.Collections.singleton;
17:
18: import java.util.HashMap;
19: import java.util.Iterator;
20: import java.util.Map;
21:
22: import org.eclipse.emf.ecore.EObject;
23: import org.eclipse.emf.ecore.EReference;
24: import org.eclipse.emf.ecore.EStructuralFeature;
25: import org.eclipse.emf.ecore.util.EcoreUtil;
26: import org.eclipse.emf.ecp.common.spi.UniqueSetting;
27: import org.eclipse.emf.ecp.ui.view.swt.reference.SelectionCompositeStrategy;
28: import org.eclipse.emf.ecp.view.spi.model.VDomainModelReference;
29: import org.eclipse.emf.ecp.view.spi.model.VFeatureDomainModelReferenceSegment;
30: import org.eclipse.emf.ecp.view.spi.model.VView;
31: import org.eclipse.emf.ecp.view.spi.model.VViewFactory;
32: import org.eclipse.emf.ecp.view.spi.model.VViewModelLoadingProperties;
33: import org.eclipse.emf.ecp.view.spi.model.VViewModelProperties;
34: import org.eclipse.emf.ecp.view.spi.provider.ViewProviderHelper;
35: import org.eclipse.emf.ecp.view.spi.table.model.VTableControl;
36: import org.eclipse.emf.ecp.view.spi.table.model.VTableDomainModelReference;
37: import org.eclipse.emfforms.bazaar.Bid;
38: import org.eclipse.emfforms.bazaar.Create;
39: import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedException;
40: import org.eclipse.emfforms.spi.core.services.databinding.emf.EMFFormsDatabindingEMF;
41: import org.eclipse.emfforms.view.spi.multisegment.model.MultiSegmentUtil;
42: import org.eclipse.emfforms.view.spi.multisegment.model.VMultiDomainModelReferenceSegment;
43: import org.osgi.service.component.annotations.Component;
44: import org.osgi.service.component.annotations.Reference;
45:
46: /**
47: * Provider of a selection composite strategy that builds a selection table viewer
48: * from a {@linkplain VTableControl table control model}.
49: *
50: * @since 1.27
51: */
52: @Component(name = "selectionTableCompositeStrategyProvider")
53: public class SelectionTableCompositeStrategyProvider implements SelectionCompositeStrategy.Provider {
54:
55:         /**
56:          * Filter key for view registration to apply the view to the context of the selection
57:          * table composite specifically in the case that some other view is also available
58:          * that is intended for the editor. The value of the filter is the name of the reference
59:          * feature for which objects are to be selected.
60:          */
61:         public static final String VIEW_FILTER_KEY = "selectionTableComposite"; //$NON-NLS-1$
62:
63:         private static final Double BID = 1.0;
64:
65:         private final Map<UniqueSetting, VTableControl> recentlyQueriedTables = new HashMap<>();
66:
67:         private EMFFormsDatabindingEMF databinding;
68:
69:         /**
70:          * Initializes me.
71:          */
72:         public SelectionTableCompositeStrategyProvider() {
73:                 super();
74:         }
75:
76:         /**
77:          * Queries my bid on a selection table composite strategy for selection of objects to add
78:          * to the given {@code reference} of an {@code owner} object.
79:          *
80:          * @param owner the owner of the reference to be edited
81:          * @param reference the reference to which to add objects
82:          *
83:          * @return my bid, or {@code null} if I have nothing to offer
84:          */
85:         @Bid
86:         public Double provides(EObject owner, EReference reference) {
87:                 final UniqueSetting key = UniqueSetting.createSetting(owner, reference);
88:                 final VTableControl table = getTableControl(key);
89:•                if (table != null) {
90:                         recentlyQueriedTables.put(key, table);
91:                 }
92:•                return table != null ? BID : null;
93:         }
94:
95:         private VTableControl getTableControl(UniqueSetting key) {
96:                 VTableControl result = recentlyQueriedTables.get(key);
97:•                if (result == null) {
98:                         result = getTableControl(key.getEObject(), key.getEStructuralFeature());
99:                 }
100:                 return result;
101:         }
102:
103:         /**
104:          * Obtain the view model for selecting objects to add the the {@code reference}
105:          * of an {@code owner}.
106:          *
107:          * @param owner the owner of the {@code reference} being edited
108:          * @param feature the reference feature being edited
109:          * @return the view model, or {@code null} if there is none
110:          */
111:         protected VTableControl getTableControl(EObject owner, EStructuralFeature feature) {
112:                 VTableControl result = null;
113:
114:                 final VViewModelProperties loadingProperties = getLoadingProperties(owner, feature);
115:
116:                 // Require our filter property to be sure only to get views that are specifically
117:                 // designed for usage in the selection composite
118:                 final VView view = ViewProviderHelper.getView(owner, loadingProperties, singleton(VIEW_FILTER_KEY));
119:
120:•                if (view != null) {
121:                         // It must have a table for our reference
122:                         result = findTableControl(view, owner, feature);
123:                 }
124:
125:                 return result;
126:         }
127:
128:         /**
129:          * Obtain the view model loading properties for filtering the applicable view models.
130:          *
131:          * @param owner the owner of the {@code reference} being edited
132:          * @param feature the reference feature being edited
133:          * @return the view model filter properties
134:          */
135:         protected VViewModelProperties getLoadingProperties(EObject owner, EStructuralFeature feature) {
136:                 final VViewModelLoadingProperties result = VViewFactory.eINSTANCE.createViewModelLoadingProperties();
137:                 result.addNonInheritableProperty(VIEW_FILTER_KEY, feature.getName());
138:                 return result;
139:         }
140:
141:         /**
142:          * Create my selection table composite strategy for selection of objects to add
143:          * to the given {@code reference} of an {@code owner} object.
144:          *
145:          * @param owner the owner of the reference to be edited
146:          * @param reference the reference to which to add objects
147:          *
148:          * @return my bid, or {@code null} if I have nothing to offer
149:          */
150:         @Create
151:         public SelectionCompositeStrategy create(EObject owner, EReference reference) {
152:                 SelectionCompositeStrategy result = null;
153:                 final UniqueSetting key = UniqueSetting.createSetting(owner, reference);
154:                 final VTableControl table = getTableControl(key);
155:
156:•                if (table != null) {
157:                         // Don't keep the cache in case the next query would have a different result
158:                         recentlyQueriedTables.remove(key);
159:                         result = strategy(table);
160:                 }
161:
162:                 return result;
163:         }
164:
165:         private SelectionCompositeStrategy strategy(VTableControl table) {
166:                 return (owner, reference, extent) -> new TableSelectionCompositeImpl(
167:                         extent, table, owner, reference);
168:         }
169:
170:         /**
171:          * Search for a table control in the given {@code view} that edits a {@code feature}.
172:          *
173:          * @param view a view to search
174:          * @param owner the owner of the {@code feature} being edited
175:          * @param feature the feature to be edited
176:          *
177:          * @return a table editing the {@code feature}, or {@code null} if none
178:          */
179:         private VTableControl findTableControl(VView view, EObject owner, EStructuralFeature feature) {
180:                 VTableControl result = null;
181:
182:•                for (final Iterator<EObject> iter = view.eAllContents(); result == null && iter.hasNext();) {
183:                         final EObject next = iter.next();
184:•                        if (next instanceof VTableControl) {
185:                                 final VTableControl table = (VTableControl) next;
186:                                 final VDomainModelReference dmr = table.getDomainModelReference();
187:•                                if (dmr == null) {
188:                                         continue;
189:                                 }
190:
191:•                                if (dmr.getSegments().isEmpty() && dmr instanceof VTableDomainModelReference) {
192:                                         // The TableDMRConverter ignores single-valued references, but we
193:                                         // have to let them be specified anyways because it's the only
194:                                         // thing that can provide the column DMRs
195:                                         final VTableDomainModelReference tdmr = (VTableDomainModelReference) dmr;
196:•                                        if (tdmr.getDomainModelEFeature() == feature
197:•                                                || resolvesTo(tdmr.getDomainModelReference(), owner, feature)) {
198:
199:                                                 // That's the one
200:                                                 result = table;
201:                                         }
202:•                                } else if (!dmr.getSegments().isEmpty() && MultiSegmentUtil.getMultiSegment(dmr).isPresent()) {
203:                                         // The MultiSegmentConverter does not handle single-value reference, but we have to let them be
204:                                         // specified anyways because it's the only thing that can provide the column DMRs.
205:                                         // Copy the dmr and replace the multi segment with a feature segment in the copied version. See if
206:                                         // this can be resolved to our target feature.
207:                                         final VDomainModelReference copiedDmr = EcoreUtil.copy(dmr);
208:                                         final VMultiDomainModelReferenceSegment multiSegment = MultiSegmentUtil.getMultiSegment(copiedDmr)
209:                                                 .get();
210:                                         copiedDmr.getSegments().remove(multiSegment);
211:                                         final VFeatureDomainModelReferenceSegment segment = VViewFactory.eINSTANCE
212:                                                 .createFeatureDomainModelReferenceSegment();
213:                                         segment.setDomainModelFeature(multiSegment.getDomainModelFeature());
214:                                         copiedDmr.getSegments().add(segment);
215:•                                        if (resolvesTo(copiedDmr, owner, feature)) {
216:                                                 result = table;
217:                                         }
218:•                                } else if (resolvesTo(dmr, owner, feature)) {
219:                                         // That's the one
220:                                         result = table;
221:                                 }
222:                         }
223:                 }
224:
225:                 return result;
226:         }
227:
228:         private boolean resolvesTo(VDomainModelReference dmr, EObject owner, EStructuralFeature feature) {
229:                 boolean result = false;
230:
231:                 EStructuralFeature.Setting setting;
232:                 try {
233:                         setting = databinding.getSetting(dmr, owner);
234:•                        result = setting != null && setting.getEStructuralFeature() == feature;
235:                 } catch (final DatabindingFailedException e) {
236:                         // This table is of no use to us
237:                 }
238:
239:                 return result;
240:         }
241:
242:         //
243:         // Component lifecycle and dependencies
244:         //
245:
246:         /**
247:          * Inject my data binding service dependency.
248:          *
249:          * @param databinding the data binding service to set
250:          */
251:         @Reference(unbind = "-")
252:         void setDatabinding(EMFFormsDatabindingEMF databinding) {
253:                 this.databinding = databinding;
254:         }
255:
256: }