001package org.nasdanika.html.ecore;
002
003import java.util.ArrayList;
004import java.util.Collection;
005import java.util.Collections;
006import java.util.Comparator;
007import java.util.HashSet;
008import java.util.List;
009import java.util.Map;
010import java.util.Set;
011import java.util.function.BooleanSupplier;
012import java.util.function.Predicate;
013import java.util.function.Supplier;
014import java.util.stream.Collectors;
015
016import org.eclipse.emf.common.util.EList;
017import org.eclipse.emf.common.util.TreeIterator;
018import org.eclipse.emf.ecore.EAttribute;
019import org.eclipse.emf.ecore.EClass;
020import org.eclipse.emf.ecore.EClassifier;
021import org.eclipse.emf.ecore.EGenericType;
022import org.eclipse.emf.ecore.ENamedElement;
023import org.eclipse.emf.ecore.EOperation;
024import org.eclipse.emf.ecore.EPackage;
025import org.eclipse.emf.ecore.EReference;
026import org.eclipse.emf.ecore.EStructuralFeature;
027import org.eclipse.emf.ecore.resource.Resource;
028import org.eclipse.emf.ecore.resource.ResourceSet;
029import org.nasdanika.common.Context;
030import org.nasdanika.common.DiagramGenerator;
031import org.nasdanika.common.ProgressMonitor;
032import org.nasdanika.common.Util;
033import org.nasdanika.emf.DiagramTextGenerator;
034import org.nasdanika.emf.EmfUtil;
035import org.nasdanika.emf.EmfUtil.EModelElementDocumentation;
036import org.nasdanika.emf.MermaidTextGenerator;
037import org.nasdanika.emf.PlantUmlTextGenerator;
038import org.nasdanika.emf.DiagramTextGenerator.RelationshipDirection;
039import org.nasdanika.emf.persistence.EObjectLoader;
040import org.nasdanika.html.Fragment;
041import org.nasdanika.html.HTMLFactory;
042import org.nasdanika.html.Tag;
043import org.nasdanika.html.TagName;
044import org.nasdanika.html.bootstrap.BootstrapFactory;
045import org.nasdanika.html.bootstrap.Table;
046import org.nasdanika.html.model.app.Action;
047import org.nasdanika.html.model.app.AppFactory;
048import org.nasdanika.html.model.app.SectionStyle;
049import org.nasdanika.ncore.util.NcoreUtil;
050
051public class EClassActionSupplier extends EClassifierActionSupplier<EClass> {
052        
053        private BooleanSupplier isGenerateLoadSpecification;
054        private Supplier<String> diagramDialectSupplier;
055
056        public EClassActionSupplier(
057                        EClass value, 
058                        Context context, 
059                        java.util.function.Function<EPackage,String> ePackagePathComputer,
060                        java.util.function.Function<String, String> javadocResolver,
061                        BooleanSupplier isGenerateLoadSpecification,
062                        Supplier<String> diagramDialectSupplier) {
063                super(value, context, ePackagePathComputer, javadocResolver);
064                this.isGenerateLoadSpecification = isGenerateLoadSpecification;
065                this.diagramDialectSupplier = diagramDialectSupplier;
066        }
067        
068        @Override
069        public org.nasdanika.html.model.app.Action execute(EClass contextEClass, ProgressMonitor progressMonitor) throws Exception {
070                Action action = super.execute(contextEClass, progressMonitor);
071                
072                action.setSectionStyle(SectionStyle.HEADER);
073                
074                // Diagram
075                String diagramMode = NcoreUtil.getNasdanikaAnnotationDetail(eObject, "diagram", "navigation");
076                String diagram = generateDiagram(1, RelationshipDirection.both, true, true, progressMonitor);
077                if (!Util.isBlank(diagram)) {
078                        switch (diagramMode) {
079                        case "content":
080                                addContent(action, diagram);
081                                break;
082                        case "none":
083                                break;
084                        case "navigation": {
085                                Action diagramAction = AppFactory.eINSTANCE.createAction();
086                                action.getNavigation().add(diagramAction);
087                                diagramAction.setText("Diagram");
088                                diagramAction.setIcon("fas fa-project-diagram");
089                                diagramAction.setLocation(eObject.getName() + "-diagram.html");
090                                addContent(diagramAction, diagram);
091                                break;
092                        }
093                        case "anonymous": {
094                                Action diagramAction = AppFactory.eINSTANCE.createAction();
095                                action.getAnonymous().add(diagramAction);
096                                diagramAction.setText("Diagram");
097                                diagramAction.setIcon("fas fa-project-diagram");
098                                diagramAction.setLocation(eObject.getName() + "-diagram.html");
099                                addContent(diagramAction, diagram);
100                                break;                  
101                        }
102                        default:
103                                throw new IllegalArgumentException("Unsupported diagram annotation value '" + diagramMode +"' on EClass " + eObject);                   
104                        }
105                }
106
107                // Generic supertypes
108                EList<EGenericType> eGenericSuperTypes = eObject.getEGenericSuperTypes();
109                if (!eGenericSuperTypes.isEmpty()) {
110                        HTMLFactory htmlFactory = context.get(HTMLFactory.class);
111                        Fragment gstf = htmlFactory.fragment(TagName.a.create(TagName.h3.create("Supertypes")).attribute("name", "supertypes"));
112
113                        Tag list = TagName.ul.create();
114                        gstf.content(list);
115                        
116                        for (EGenericType superType: eGenericSuperTypes) {
117                                Tag listItem = TagName.li.create();
118                                list.content(listItem);
119                                genericType(superType, eObject, listItem.getContent(), progressMonitor);
120                        }
121                        addContent(action, gstf.toString());
122                }
123                
124                // Subtypes
125                Collection<EClass> eSubTypes = getSubTypes(eObject).stream().sorted((a,b) -> a.getName().compareTo(b.getName())).collect(Collectors.toList());
126                if (!eSubTypes.isEmpty()) {
127                        HTMLFactory htmlFactory = context.get(HTMLFactory.class);
128                        Fragment gstf = htmlFactory.fragment(TagName.a.create(TagName.h3.create("Subtypes")).attribute("name", "subtypes"));
129
130                        Tag list = TagName.ul.create();
131                        gstf.content(list);
132                        
133                        for (EClass subType: eSubTypes) {
134                                list.content(TagName.li.create(link(subType, eObject)));
135                        }
136                        addContent(action, gstf.toString());
137                }
138                
139                // Referrers
140                Collection<EClass> referrers = getReferrers().stream().sorted((a,b) -> a.getName().compareTo(b.getName())).collect(Collectors.toList());
141                if (!referrers.isEmpty()) {
142                        HTMLFactory htmlFactory = context.get(HTMLFactory.class);
143                        Fragment gstf = htmlFactory.fragment(TagName.a.create(TagName.h3.create("Referrers")).attribute("name", "referrers"));
144
145                        Tag list = TagName.ul.create();
146                        gstf.content(list);
147                        
148                        for (EClass referrer: referrers) {
149                                list.content(TagName.li.create(link(referrer, eObject)));
150                        }
151                        addContent(action, gstf.toString());
152                }
153                
154                // Uses
155                Collection<EClass> uses = getUses().stream().sorted((a,b) -> a.getName().compareTo(b.getName())).collect(Collectors.toList());
156                if (!uses.isEmpty()) {
157                        HTMLFactory htmlFactory = context.get(HTMLFactory.class);
158                        Fragment gstf = htmlFactory.fragment(TagName.a.create(TagName.h3.create("Uses")).attribute("name", "uses"));
159
160                        Tag list = TagName.ul.create();
161                        gstf.content(list);
162                        
163                        for (EClass use: uses) {
164                                list.content(TagName.li.create(link(use, eObject)));
165                        }
166                        addContent(action, gstf.toString());
167                }
168                
169                Comparator<ENamedElement> namedElementComparator = (a,b) -> a.getName().compareTo(b.getName());
170                
171                List<EAttribute> allAttributes = eObject.getEAllAttributes().stream().sorted((a,b) ->  a.getName().compareTo(b.getName())).collect(Collectors.toList());
172                List<EReference> allReferences = eObject.getEAllReferences().stream().sorted((a,b) ->  a.getName().compareTo(b.getName())).collect(Collectors.toList());
173                List<EOperation> allOperations = eObject.getEAllOperations().stream().sorted((a,b) ->  a.getName().compareTo(b.getName())).collect(Collectors.toList());                
174                EList<EGenericType> allGenericSupertypes = eObject.getEAllGenericSuperTypes();
175                
176                if (allAttributes.size() + allReferences.size() + allOperations.size() + allGenericSupertypes.size()  != 0) {   
177                        Action allGroup = AppFactory.eINSTANCE.createAction();
178                        allGroup.setText("All");
179                        allGroup.setUuid(action.getUuid() + "-all");
180                        action.getNavigation().add(allGroup);
181                        
182                        generateAllAttributes(allAttributes, allGroup, progressMonitor);
183                        generateAllReferences(allReferences, allGroup, progressMonitor);
184                        generateAllOperations(allOperations, allGroup, progressMonitor);                        
185                        generateAllGenericSupertypes(allGenericSupertypes, allGroup, progressMonitor);                  
186                }
187        
188                // No load specification for EMap entries.
189                if (isGenerateLoadSpecification.getAsBoolean() && Map.Entry.class != instanceClass) { 
190                        generateLoadSpecification(action, namedElementComparator, progressMonitor);
191                }
192                
193//              TODO - Table (list) of contents
194//              Map<String, Object> locConfig = new LinkedHashMap<>();
195//              locConfig.put("tooltip", true);
196//              locConfig.put("header", "Members");             
197//              locConfig.put("role", Action.Role.SECTION);             
198//              addContent(data, Collections.singletonMap("component-list-of-contents", locConfig));
199                
200                EList<Action> sections = action.getSections();
201                if (!eObject.getEAttributes().isEmpty()) {
202                        Action attributesCategory = AppFactory.eINSTANCE.createAction();
203                        attributesCategory.setText("Attributes");
204                        attributesCategory.setName("attributes");
205                        attributesCategory.setSectionStyle(SectionStyle.HEADER);
206                        sections.add(attributesCategory);
207                        EList<Action> attributes = attributesCategory.getSections();
208                        for (EStructuralFeature sf: eObject.getEAttributes().stream().sorted((a,b) ->  a.getName().compareTo(b.getName())).collect(Collectors.toList())) {
209                                attributes.add(adaptChild(sf).execute(null, progressMonitor));
210                        }
211                }
212                
213                if (!eObject.getEReferences().isEmpty()) {
214                        Action referencesCategory = AppFactory.eINSTANCE.createAction();
215                        referencesCategory.setText("References");
216                        referencesCategory.setName("references");
217                        referencesCategory.setSectionStyle(SectionStyle.HEADER);
218                        sections.add(referencesCategory);
219                        EList<Action> references = referencesCategory.getSections();                    
220                        for (EStructuralFeature sf: eObject.getEReferences().stream().sorted((a,b) ->  a.getName().compareTo(b.getName())).collect(Collectors.toList())) {
221                                references.add(adaptChild(sf).execute(null, progressMonitor));
222                        }
223                }
224                
225                if (!eObject.getEOperations().isEmpty()) {
226                        Action operationsCategory = AppFactory.eINSTANCE.createAction();
227                        operationsCategory.setText("Operations");
228                        operationsCategory.setName("operations");
229                        operationsCategory.setSectionStyle(SectionStyle.HEADER);
230                        sections.add(operationsCategory);
231                        EList<Action> operations = operationsCategory.getSections();                    
232                        for (EOperation eOp: eObject.getEOperations().stream().sorted((a,b) ->  a.getName().compareTo(b.getName())).collect(Collectors.toList())) {
233                                operations.add(adaptChild(eOp).execute(null, progressMonitor));                 
234                        }
235                }
236                
237                if (eObject.isInterface()) {
238                        action.setIcon(ICONS_BASE + "EInterface.gif");                  
239                }               
240                
241                return action;
242        }
243
244        private void generateAllGenericSupertypes(List<EGenericType> allGenericSupertypes, Action allGroup, ProgressMonitor progressMonitor) throws Exception {         
245                if (!allGenericSupertypes.isEmpty()) {
246                        String inheritanceDiagram = generateInheritanceDiagram(0, RelationshipDirection.both, true, true, progressMonitor);
247                        if (!Util.isBlank(inheritanceDiagram)) {
248                                Action allSupertypesAction = AppFactory.eINSTANCE.createAction();
249                                allSupertypesAction.setText("Supertypes");
250                                allSupertypesAction.setLocation(eObject.getName() + "-all-supertypes.html");
251                                allSupertypesAction.setSectionStyle(SectionStyle.HEADER);
252                                allGroup.getChildren().add(allSupertypesAction);
253                                
254                                Tag list = TagName.ul.create();
255                                
256                                for (EGenericType superType: allGenericSupertypes) {
257                                        Tag listItem = TagName.li.create();
258                                        list.content(listItem);
259                                        genericType(superType, eObject, listItem.getContent(), progressMonitor);
260                                }
261                                addContent(allSupertypesAction, list.toString());                       
262                                addContent(allSupertypesAction, inheritanceDiagram);
263                        }                       
264                }
265        }
266        
267        protected String generateInheritanceDiagram(
268                        int depth, 
269                        RelationshipDirection relationshipDirection,
270                        boolean appendAttributes,
271                        boolean appendOperations,
272                        ProgressMonitor monitor) throws Exception {
273                
274                StringBuilder sb = new StringBuilder();
275                DiagramTextGenerator gen = getDiagramTextGenerator(sb, appendAttributes, appendOperations);
276                if (gen == null) {
277                        return null;
278                }
279                List<EClass> diagramElements = new ArrayList<>();
280                diagramElements.add(eObject);
281                diagramElements.addAll(eObject.getEAllSuperTypes());
282                gen.appendWithRelationships(diagramElements, relationshipDirection, depth);
283                
284                return context.get(DiagramGenerator.class).generateUmlDiagram(sb.toString());
285        }
286        
287        
288        private void generateAllOperations(List<EOperation> allOperations, Action allGroup, ProgressMonitor progressMonitor) throws Exception {         
289                if (!allOperations.isEmpty()) {
290                        Action allOperationsAction = AppFactory.eINSTANCE.createAction();
291                        allOperationsAction.setText("Operations");
292                        allOperationsAction.setLocation(eObject.getName() + "-all-operations.html");
293                        allOperationsAction.setSectionStyle(SectionStyle.HEADER);
294                        allGroup.getChildren().add(allOperationsAction);
295                        
296                        EList<Action> operations = allOperationsAction.getSections();                   
297                        for (EOperation eOp: allOperations) {
298                                operations.add(adaptChild(eOp).execute(eObject, progressMonitor));                      
299                        }
300                }
301        }
302
303        private void generateAllReferences(List<EReference> allReferences,      Action allGroup, ProgressMonitor progressMonitor) throws Exception {            
304                if (!allReferences.isEmpty()) {
305                        Action allReferencesAction = AppFactory.eINSTANCE.createAction();
306                        allReferencesAction.setText("References");
307                        allReferencesAction.setLocation(eObject.getName() + "-all-references.html");
308                        allReferencesAction.setSectionStyle(SectionStyle.HEADER);
309                        allGroup.getChildren().add(allReferencesAction);
310                        
311                        EList<Action> references = allReferencesAction.getSections();                   
312                        for (EStructuralFeature sf: allReferences) {
313                                references.add(adaptChild(sf).execute(eObject, progressMonitor));
314                        }
315                }
316        }
317
318        private void generateAllAttributes(List<EAttribute> allAttributes, Action allGroup,     ProgressMonitor progressMonitor) throws Exception {             
319                if (!allAttributes.isEmpty()) {
320                        Action allAttributesAction = AppFactory.eINSTANCE.createAction();
321                        allAttributesAction.setText("Attributes");
322                        allAttributesAction.setLocation(eObject.getName() + "-all-attributes.html");
323                        allAttributesAction.setSectionStyle(SectionStyle.HEADER);
324                        allGroup.getChildren().add(allAttributesAction);
325                        
326                        EList<Action> attributes = allAttributesAction.getSections();
327                        for (EStructuralFeature sf: allAttributes) {
328                                attributes.add(adaptChild(sf).execute(eObject, progressMonitor));
329                        }
330                }
331        }
332
333        private void generateLoadSpecification(
334                        Action action, 
335                        Comparator<ENamedElement> namedElementComparator,
336                        ProgressMonitor progressMonitor) throws Exception {
337                
338                // Load specification
339                if (!eObject.isAbstract() && "true".equals(NcoreUtil.getNasdanikaAnnotationDetail(eObject, EObjectLoader.IS_LOADABLE, "true"))) {
340                        Action loadSpecificationAction = AppFactory.eINSTANCE.createAction();
341                        loadSpecificationAction.setText("Load specification");
342                        loadSpecificationAction.setLocation(eObject.getName() + "-load-specification.html");                    
343                        action.getNavigation().add(loadSpecificationAction);
344                        
345                        EModelElementDocumentation loadDoc = EmfUtil.getLoadDocumentation(eObject);
346                        if (loadDoc != null) {
347                                loadSpecificationAction.getContent().add(interpolatedMarkdown(loadDoc.getDocumentation(), loadDoc.getLocation(), progressMonitor));
348                        }
349                        
350                        Tag toc = TagName.ul.create();
351                        
352                        Predicate<EStructuralFeature> predicate = sf -> sf.isChangeable() && "true".equals(NcoreUtil.getNasdanikaAnnotationDetail(sf, EObjectLoader.IS_LOADABLE, "true"));
353                        for (EStructuralFeature sf: eObject.getEAllStructuralFeatures().stream().filter(predicate).sorted(namedElementComparator).collect(Collectors.toList())) {
354                                Action featureAction = AppFactory.eINSTANCE.createAction();
355                                String key = NcoreUtil.getNasdanikaAnnotationDetail(sf, EObjectLoader.LOAD_KEY, NcoreUtil.getFeatureKey(eObject, sf));
356                                featureAction.setText(key);
357                                String sectionAnchor = "key-section-" + key;
358                                
359                                featureAction.setName(sectionAnchor);                   
360                                loadSpecificationAction.getSections().add(featureAction);
361
362                                // Properties table
363                                Table table = context.get(BootstrapFactory.class).table();
364                                table.toHTMLElement().style().width("auto");
365                                
366                                genericType(sf.getEGenericType(), eObject, ETypedElementActionSupplier.addRow(table, "Type"), progressMonitor);
367                                
368                                boolean isDefaultFeature = EObjectLoader.isDefaultFeature(eObject, sf);
369                                if (isDefaultFeature) {
370                                        ETypedElementActionSupplier.addRow(table, "Default").add("true");                               
371                                }
372                                toc.accept(TagName.li.create(TagName.a.create(key).attribute("href", "#" + sectionAnchor).attribute("style", "font-weight:bold", isDefaultFeature)));
373                                
374                                boolean isHomogenous = "true".equals(NcoreUtil.getNasdanikaAnnotationDetail(sf, EObjectLoader.IS_HOMOGENOUS)) || NcoreUtil.getNasdanikaAnnotationDetail(sf, EObjectLoader.REFERENCE_TYPE) != null;
375                                if (isHomogenous) {
376                                        ETypedElementActionSupplier.addRow(table, "Homogenous").add("true");                                                                    
377                                }
378                                
379                                boolean isStrictContainment = isHomogenous && "true".equals(NcoreUtil.getNasdanikaAnnotationDetail(sf, EObjectLoader.IS_STRICT_CONTAINMENT));                   
380                                if (isStrictContainment) {
381                                        ETypedElementActionSupplier.addRow(table, "Strict containment").add("true");                                                                    
382                                }
383                                
384                                Object[] exclusiveWith = EObjectLoader.getExclusiveWith(eObject, sf, EObjectLoader.LOAD_KEY_PROVIDER);
385                                if (exclusiveWith.length != 0) {
386                                        Tag ul = TagName.ul.create();
387                                        for (Object exw: exclusiveWith) {
388                                                ul.content(TagName.li.create(exw));
389                                        }
390                                        ETypedElementActionSupplier.addRow(table, "Exclusive with").add(ul);                            
391                                }
392
393                                addContent(featureAction, table.toString());
394                                
395                                EModelElementDocumentation featureLoadDoc = EmfUtil.getLoadDocumentation(sf);
396                                if (featureLoadDoc == null) {
397//                                      featureLoadDoc = EObjectAdaptable.getResourceContext(sf).getString("documentation", EcoreUtil.getDocumentation(sf));
398//                                      if (Util.isBlank(featureLoadDoc)) {
399                                                featureLoadDoc = EmfUtil.getDocumentation(sf);
400//                                      }                                       
401                                }
402                                if (featureLoadDoc != null) {
403                                        featureAction.getContent().add(interpolatedMarkdown(context.interpolateToString(featureLoadDoc.getDocumentation()), featureLoadDoc.getLocation(), progressMonitor));
404                                }
405                        }       
406                        
407                        addContent(loadSpecificationAction, toc.toString());
408                }
409        }
410        
411        protected DiagramTextGenerator getDiagramTextGenerator(StringBuilder sb, boolean appendAttributes, boolean appendOperations) {
412                String dialect = diagramDialectSupplier.get();
413                if (Util.isBlank(dialect)) {
414                        return null;
415                }
416                switch (dialect) {
417                case DiagramGenerator.UML_DIALECT:
418                        return new PlantUmlTextGenerator(sb, ec -> path(ec, eObject), this::getEModelElementFirstDocSentence) {
419                                
420                                @Override
421                                protected Collection<EClass> getSubTypes(EClass eClass) {
422                                        return EClassActionSupplier.this.getSubTypes(eClass);
423                                }
424                                
425                                @Override
426                                protected Collection<EClass> getReferrers(EClass eClass) {
427                                        return EClassActionSupplier.this.getReferrers(eClass);
428                                }
429                                
430                                @Override
431                                protected Collection<EClass> getUses(EClassifier eClassifier) {
432                                        return EClassActionSupplier.this.getUses(eClassifier);
433                                }
434                                
435                                @Override
436                                protected boolean isAppendAttributes(EClass eClass) {
437                                        return appendAttributes;
438                                }
439                                
440                                @Override
441                                protected boolean isAppendOperations(EClass eClass) {
442                                        return appendOperations;
443                                }
444                                
445                        };
446                case DiagramGenerator.MERMAID_DIALECT:
447                        return new MermaidTextGenerator(sb, ec -> path(ec, eObject), this::getEModelElementFirstDocSentence) {
448                                
449                                @Override
450                                protected Collection<EClass> getSubTypes(EClass eClass) {
451                                        return EClassActionSupplier.this.getSubTypes(eClass);
452                                }
453                                
454                                @Override
455                                protected Collection<EClass> getReferrers(EClass eClass) {
456                                        return EClassActionSupplier.this.getReferrers(eClass);
457                                }
458                                
459                                @Override
460                                protected Collection<EClass> getUses(EClassifier eClassifier) {
461                                        return EClassActionSupplier.this.getUses(eClassifier);
462                                }
463                                
464                                @Override
465                                protected boolean isAppendAttributes(EClass eClass) {
466                                        return appendAttributes;
467                                }
468                                
469                                @Override
470                                protected boolean isAppendOperations(EClass eClass) {
471                                        return appendOperations;
472                                }
473                                
474                        };
475                default:
476                        throw new UnsupportedOperationException("Unsupported dialect: " + dialect);
477                }                                       
478        }
479        
480        protected String generateDiagram(
481                        int depth, 
482                        DiagramTextGenerator.RelationshipDirection relationshipDirection,
483                        boolean appendAttributes,
484                        boolean appendOperations,
485                        ProgressMonitor monitor) throws Exception {
486
487                DiagramGenerator diagramGenerator = context.get(DiagramGenerator.class);                
488                
489                StringBuilder sb = new StringBuilder();
490
491                DiagramTextGenerator gen = getDiagramTextGenerator(sb, appendAttributes, appendOperations);
492                if (gen == null) {
493                        return null;
494                }
495                gen.appendWithRelationships(Collections.singleton(eObject), relationshipDirection, depth);
496                
497                return diagramGenerator.generateUmlDiagram(sb.toString());
498        }
499                
500        /**
501         * Override to return a list of sub-types of given EClass. 
502         * This implementation returns all sub-types found in the resource set. 
503         * @param eClass
504         * @return
505         */
506        protected Collection<EClass> getSubTypes(EClass eClass) {
507                TreeIterator<?> acit;
508                Resource eResource = eClass.eResource();
509                if (eResource == null) {
510                        EPackage ePackage = eClass.getEPackage();
511                        if (ePackage == null) {
512                                return Collections.emptySet();
513                        }
514                        acit = ePackage.eAllContents();
515                } else {
516                        ResourceSet resourceSet = eResource.getResourceSet();
517                        acit = resourceSet == null ? eResource.getAllContents() : resourceSet.getAllContents();
518                }
519                Set<EClass> ret = new HashSet<>();
520                acit.forEachRemaining(obj -> {
521                        if (obj instanceof EClass && ((EClass) obj).getESuperTypes().contains(eClass)) {
522                                ret.add((EClass) obj);
523                        }
524                });
525                return ret;
526        }
527                        
528        /**
529         * @return Referrers to this class
530         */     
531        protected Collection<EClass> getReferrers() {
532                return getReferrers(eObject);
533        }
534        
535}