Skip to content

Package: EMFUtils

EMFUtils

nameinstructionbranchcomplexitylinemethod
adapt(EObject, Class)
M: 0 C: 29
100%
M: 0 C: 0
100%
M: 0 C: 1
100%
M: 0 C: 7
100%
M: 0 C: 1
100%
equalFeature(EObject, EObject, EStructuralFeature)
M: 0 C: 36
100%
M: 0 C: 10
100%
M: 0 C: 6
100%
M: 0 C: 8
100%
M: 0 C: 1
100%
filteredEquals(EObject, EObject, EStructuralFeature[])
M: 2 C: 47
96%
M: 1 C: 13
93%
M: 1 C: 7
88%
M: 0 C: 13
100%
M: 0 C: 1
100%
getAllRegisteredEPackages()
M: 3 C: 34
92%
M: 1 C: 3
75%
M: 1 C: 2
67%
M: 3 C: 8
73%
M: 0 C: 1
100%
getSubClasses(EClass)
M: 0 C: 53
100%
M: 1 C: 13
93%
M: 1 C: 7
88%
M: 0 C: 9
100%
M: 0 C: 1
100%
lambda$4(EObject, Class, AdapterFactory)
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%

Coverage

1: /*******************************************************************************
2: * Copyright (c) 2011-2014 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: ******************************************************************************/
14: package org.eclipse.emf.ecp.common.spi;
15:
16: import java.util.Arrays;
17: import java.util.Collection;
18: import java.util.HashSet;
19: import java.util.LinkedHashSet;
20: import java.util.List;
21: import java.util.Optional;
22: import java.util.Set;
23:
24: import org.eclipse.emf.ecore.EClass;
25: import org.eclipse.emf.ecore.EClassifier;
26: import org.eclipse.emf.ecore.EObject;
27: import org.eclipse.emf.ecore.EPackage;
28: import org.eclipse.emf.ecore.EPackage.Registry;
29: import org.eclipse.emf.ecore.EStructuralFeature;
30: import org.eclipse.emf.ecore.EcorePackage;
31: import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
32:
33: /**
34: * Util class for basic EMF.
35: *
36: * @author Eugen Neufeld
37: * @since 1.5
38: *
39: */
40: public final class EMFUtils {
41:
42:         private EMFUtils() {
43:         }
44:
45:         /**
46:          * This method looks through all known {@link EPackage}s to find all concrete subclasses for the provided super
47:          * class (abstract classes and interfaces will be ignored). If the EClass is EObject, all non abstract and non
48:          * interface classes will be returned.
49:          *
50:          * @param superClass
51:          * - the class for which to get the subclasses
52:          * @return a {@link Collection} of {@link EClass EClasses}
53:          */
54:         public static Collection<EClass> getSubClasses(EClass superClass) {
55:                 final Collection<EClass> classes = new HashSet<EClass>();
56:•                for (final EPackage ePackage : getAllRegisteredEPackages()) {
57:•                        for (final EClassifier eClassifier : ePackage.getEClassifiers()) {
58:•                                if (eClassifier instanceof EClass) {
59:                                         final EClass eClass = (EClass) eClassifier;
60:•                                        if (!eClass.isAbstract() && !eClass.isInterface()
61:•                                                && (EcorePackage.eINSTANCE.getEObject() == superClass || superClass.isSuperTypeOf(eClass))) {
62:                                                 classes.add(eClass);
63:                                         }
64:                                 }
65:                         }
66:                 }
67:                 return classes;
68:         }
69:
70:         /**
71:          * Returns the set of all known {@link EPackage EPackages}.
72:          *
73:          * @return the Set of all known {@link EPackage Epackages}
74:          */
75:         public static Set<EPackage> getAllRegisteredEPackages() {
76:                 final Set<EPackage> ePackages = new HashSet<EPackage>();
77:                 final Set<String> namespaceURIs = new LinkedHashSet<String>(Registry.INSTANCE.keySet());
78:•                for (final String nsURI : namespaceURIs) {
79:                         EPackage ePackage;
80:                         try {
81:                                 ePackage = Registry.INSTANCE.getEPackage(nsURI);
82:                         }
83:                         // BEGIN SUPRESS CATCH EXCEPTION
84:                         catch (final Exception ex) {// END SUPRESS CATCH EXCEPTION
85:                                 /* If there is a wrongly configured EPackage the call to getEPackage might throw a runtime exception */
86:                                 /* Catch here, so we can still loop through the whole registry */
87:                                 continue;
88:                         }
89:•                        if (ePackage == null) {
90:                                 /*
91:                                  * this case is actually possible! we should only collect non null
92:                                  * epackages
93:                                  */
94:                                 continue;
95:                         }
96:                         ePackages.add(ePackage);
97:                 }
98:                 return ePackages;
99:         }
100:
101:         /**
102:          * Check two EObjects for equality by comparing their EClass and all their features' values.
103:          * Additionally, an arbitrary number of features can be supplied whose values will <strong>not</strong> be compared
104:          * to determine equality. This can be used to implement a custom equality check in the client.
105:          *
106:          * @param property The EObject triggering the comparison, might be <code>null</code>.
107:          * @param other The other style EObject, might be <code>null</code>
108:          * @param filteredFeatures Features that are ignored in the equality check.
109:          * @return <code>true</code> if the EClass and the values of all features are equal or if both EObjects are
110:          * <code>null</code>, <code>false</code> otherwise
111:          * @since 1.18
112:          */
113:         public static boolean filteredEquals(EObject property, EObject other,
114:                 EStructuralFeature... filteredFeatures) {
115:•                if (property == null) {
116:•                        return other == null;
117:                 }
118:•                if (other == null) {
119:                         return false;
120:                 }
121:•                if (property.eClass() != other.eClass()) {
122:                         return false;
123:                 }
124:
125:                 final List<EStructuralFeature> filter = Arrays.asList(filteredFeatures);
126:•                for (final EStructuralFeature esf : property.eClass().getEAllStructuralFeatures()) {
127:•                        if (filter.contains(esf)) {
128:                                 continue;
129:                         }
130:•                        if (!equalFeature(property, other, esf)) {
131:                                 return false;
132:                         }
133:                 }
134:                 return true;
135:         }
136:
137:         // extract feature comparison to reduce N-Path complexity of filteredEquals
138:         private static boolean equalFeature(EObject eObject1, EObject eObject2,
139:                 final EStructuralFeature structuralFeature) {
140:•                if (structuralFeature.isUnsettable()
141:•                        && eObject1.eIsSet(structuralFeature) != eObject2.eIsSet(structuralFeature)) {
142:                         return false;
143:                 }
144:•                if (eObject1.eGet(structuralFeature) == null) {
145:•                        return eObject2.eGet(structuralFeature) == null;
146:                 }
147:•                if (!eObject1.eGet(structuralFeature).equals(eObject2.eGet(structuralFeature))) {
148:                         return false;
149:                 }
150:                 return true;
151:         }
152:
153:         /**
154:          * Tries to adapt the given EObject to the given class. This is done with help of the EObject's
155:          * AdapterFactoryEditingDomain.
156:          *
157:          * @param <A> The adapter type
158:          * @param object The {@link EObject} to adapt
159:          * @param adapter The adapter class
160:          * @return The adapted EObject or nothing if the EObjects AdapterFactoryEditingDomain could not be determined or the
161:          * EObject could not be adapted to the target type.
162:          * @since 1.21
163:          */
164:         public static <A> Optional<A> adapt(EObject object, Class<A> adapter) {
165:                 return Optional.ofNullable(object)
166:                         .map(AdapterFactoryEditingDomain::getEditingDomainFor)
167:                         .filter(AdapterFactoryEditingDomain.class::isInstance)
168:                         .map(AdapterFactoryEditingDomain.class::cast)
169:                         .map(AdapterFactoryEditingDomain::getAdapterFactory)
170:                         .map(factory -> factory.adapt(object, adapter))
171:                         .map(adapter::cast);
172:         }
173: }