Skip to content

Package: MappedEClassControlSWTRenderer

MappedEClassControlSWTRenderer

nameinstructionbranchcomplexitylinemethod
MappedEClassControlSWTRenderer(VControl, ViewModelContext, ReportService)
M: 0 C: 6
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 2
100%
M: 0 C: 1
100%
getValueEClass(VMappingDomainModelReferenceSegment)
M: 6 C: 38
86%
M: 3 C: 3
50%
M: 3 C: 1
25%
M: 3 C: 9
75%
M: 0 C: 1
100%
lambda$4(Object[])
M: 0 C: 18
100%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 0 C: 4
100%
M: 0 C: 1
100%
linkValue(Shell)
M: 6 C: 114
95%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 2 C: 30
94%
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: * Lucas Koehler - initial API and implementation
13: */
14: package org.eclipse.emfforms.internal.ide.view.mappingsegment;
15:
16: import java.util.Collection;
17: import java.util.Collections;
18: import java.util.List;
19: import java.util.Optional;
20: import java.util.Set;
21: import java.util.stream.Collectors;
22:
23: import javax.inject.Inject;
24:
25: import org.eclipse.core.databinding.observable.IObserving;
26: import org.eclipse.core.databinding.observable.value.IObservableValue;
27: import org.eclipse.core.runtime.IStatus;
28: import org.eclipse.core.runtime.Status;
29: import org.eclipse.emf.common.notify.AdapterFactory;
30: import org.eclipse.emf.ecore.EClass;
31: import org.eclipse.emf.ecore.EReference;
32: import org.eclipse.emf.ecore.EStructuralFeature;
33: import org.eclipse.emf.ecp.common.spi.EMFUtils;
34: import org.eclipse.emf.ecp.view.internal.editor.controls.EditableEReferenceLabelControlSWTRenderer;
35: import org.eclipse.emf.ecp.view.spi.context.ViewModelContext;
36: import org.eclipse.emf.ecp.view.spi.editor.controls.SelectedFeatureViewService;
37: import org.eclipse.emf.ecp.view.spi.model.VControl;
38: import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
39: import org.eclipse.emf.edit.provider.ReflectiveItemProviderAdapterFactory;
40: import org.eclipse.emf.edit.ui.provider.AdapterFactoryLabelProvider;
41: import org.eclipse.emfforms.spi.common.report.ReportService;
42: import org.eclipse.emfforms.spi.core.services.databinding.DatabindingFailedException;
43: import org.eclipse.emfforms.spi.view.mappingsegment.model.VMappingDomainModelReferenceSegment;
44: import org.eclipse.jface.viewers.ITreeContentProvider;
45: import org.eclipse.jface.viewers.Viewer;
46: import org.eclipse.jface.viewers.ViewerComparator;
47: import org.eclipse.jface.window.Window;
48: import org.eclipse.swt.widgets.Shell;
49: import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
50:
51: /**
52: * Control for the <code>mappedClass</code> feature of {@link VMappingDomainModelReferenceSegment}.
53: *
54: * @author Lucas Koehler
55: *
56: */
57: public class MappedEClassControlSWTRenderer extends EditableEReferenceLabelControlSWTRenderer {
58:
59:         /**
60:          * @param vElement the view model element to be rendered
61:          * @param viewContext the view context
62:          * @param reportService the {@link ReportService}
63:          */
64:         @Inject
65:         public MappedEClassControlSWTRenderer(VControl vElement, ViewModelContext viewContext,
66:                 ReportService reportService) {
67:                 super(vElement, viewContext, reportService);
68:         }
69:
70:         /**
71:          * Content provider which calculates an EClass's children based on the given list of EClasses. The children of an
72:          * EClass are all EClasses which have the EClass as a direct super type.
73:          */
74:         private static final class EClassTreeContentProvider implements ITreeContentProvider {
75:                 private final Collection<EClass> subClasses;
76:
77:                 EClassTreeContentProvider(Collection<EClass> subClasses) {
78:                         this.subClasses = subClasses;
79:                 }
80:
81:                 @Override
82:                 public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {
83:                         // Do nothing
84:                 }
85:
86:                 @Override
87:                 public void dispose() {
88:                         // Do nothing
89:                 }
90:
91:                 @Override
92:                 public boolean hasChildren(Object element) {
93:                         if (EClass.class.isInstance(element)) {
94:                                 final Object[] children = getChildren(element);
95:                                 return children != null && children.length > 0;
96:                         }
97:                         return false;
98:                 }
99:
100:                 @Override
101:                 public Object getParent(Object element) {
102:                         if (EClass.class.isInstance(element)) {
103:                                 return ((EClass) element).eContainer();
104:                         }
105:                         return null;
106:                 }
107:
108:                 @Override
109:                 public Object[] getElements(Object inputElement) {
110:                         return getChildren(inputElement);
111:                 }
112:
113:                 @Override
114:                 public Object[] getChildren(Object parentElement) {
115:                         if (EClass.class.isInstance(parentElement)) {
116:                                 final EClass eClass = (EClass) parentElement;
117:                                 final List<EClass> directSubClasses = subClasses.stream()
118:                                         .filter(c -> c.getESuperTypes().contains(eClass))
119:                                         .collect(Collectors.toList());
120:                                 return directSubClasses.toArray();
121:                         }
122:                         if (Collection.class.isInstance(parentElement)) {
123:                                 return Collection.class.cast(parentElement).toArray();
124:                         }
125:                         return null;
126:                 }
127:         }
128:
129:         @Override
130:         protected void linkValue(Shell shell) {
131:                 IObservableValue<?> observableValue;
132:                 try {
133:                         observableValue = getEMFFormsDatabinding()
134:                                 .getObservableValue(getVElement().getDomainModelReference(), getViewModelContext().getDomainModel());
135:                 } catch (final DatabindingFailedException ex) {
136:                         showLinkValueFailedMessageDialog(shell, ex);
137:                         return;
138:                 }
139:                 final VMappingDomainModelReferenceSegment mappingSegment = (VMappingDomainModelReferenceSegment) ((IObserving) observableValue)
140:                         .getObserved();
141:                 observableValue.dispose();
142:                 final ComposedAdapterFactory adapterFactory = new ComposedAdapterFactory(new AdapterFactory[] {
143:                         new ReflectiveItemProviderAdapterFactory(),
144:                         new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE) });
145:                 final AdapterFactoryLabelProvider labelProvider = new AdapterFactoryLabelProvider(
146:                         adapterFactory);
147:
148:                 final Optional<EClass> valueEClass = getValueEClass(mappingSegment);
149:                 final Set<EClass> input = valueEClass.map(Collections::singleton).orElseGet(Collections::emptySet);
150:                 final Collection<EClass> subClasses = valueEClass.map(EMFUtils::getSubClasses).orElseGet(Collections::emptySet);
151:                 final EClassTreeContentProvider contentProvider = new EClassTreeContentProvider(subClasses);
152:                 final ElementTreeSelectionDialog dialog = new ElementTreeSelectionDialog(shell, labelProvider, contentProvider);
153:                 dialog.setAllowMultiple(false);
154:                 dialog.setValidator(selection -> {
155:•                        if (selection.length != 0 && EClass.class.isInstance(selection[0])) {
156:
157:                                 return Status.OK_STATUS;
158:                         }
159:                         return new Status(IStatus.ERROR, "org.eclipse.emfforms.ide.view.mappingsegment", //$NON-NLS-1$
160:                                 "This is not an EClass."); //$NON-NLS-1$
161:                 });
162:
163:                 dialog.setInput(input);
164:                 dialog.setMessage("Select an EClass."); //$NON-NLS-1$
165:                 dialog.setTitle("Select an EClass"); //$NON-NLS-1$
166:                 dialog.setComparator(new ViewerComparator());
167:                 final int result = dialog.open();
168:•                if (Window.OK == result) {
169:                         final Object selection = dialog.getFirstResult();
170:•                        if (EClass.class.isInstance(selection)) {
171:                                 final EClass selectedFeature = (EClass) selection;
172:                                 mappingSegment.setMappedClass(selectedFeature);
173:                         }
174:                 }
175:                 labelProvider.dispose();
176:         }
177:
178:         /**
179:          * @return a collection of the selectable {@link org.eclipse.emf.ecore.EClass EClasses}.
180:          * The selectable EClasses are all subclasses of the map's values' class.
181:          */
182:         private Optional<EClass> getValueEClass(VMappingDomainModelReferenceSegment mappingSegment) {
183:                 // get map type from a view model service set by the advanced dmr creation wizard
184:                 final SelectedFeatureViewService service = getViewModelContext().getService(SelectedFeatureViewService.class);
185:•                if (service == null) {
186:                         return Optional.empty();
187:                 }
188:                 final EStructuralFeature mapFeature = service.getFeature();
189:•                if (!EReference.class.isInstance(mapFeature)) {
190:                         return Optional.empty();
191:                 }
192:                 final EClass referenceMap = EReference.class.cast(mapFeature).getEReferenceType();
193:                 final EStructuralFeature valueFeature = referenceMap.getEStructuralFeature("value"); //$NON-NLS-1$
194:•                if (!EReference.class.isInstance(valueFeature)) {
195:                         return Optional.empty();
196:                 }
197:                 final EReference valueReference = EReference.class.cast(valueFeature);
198:
199:                 return Optional.ofNullable(valueReference.getEReferenceType());
200:         }
201:
202: }