/******************************************************************************* * Copyright (c) 2010, 2015 Willink Transformations and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * E.D.Willink - initial API and implementation *******************************************************************************/ package org.eclipse.ocl.xtext.base.as2cs; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.log4j.Logger; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EFactory; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.jdt.annotation.NonNull; import org.eclipse.jdt.annotation.Nullable; import org.eclipse.ocl.pivot.CollectionType; import org.eclipse.ocl.pivot.CompletePackage; import org.eclipse.ocl.pivot.Element; import org.eclipse.ocl.pivot.Model; import org.eclipse.ocl.pivot.NamedElement; import org.eclipse.ocl.pivot.Namespace; import org.eclipse.ocl.pivot.Package; import org.eclipse.ocl.pivot.PivotPackage; import org.eclipse.ocl.pivot.Property; import org.eclipse.ocl.pivot.TemplateSignature; import org.eclipse.ocl.pivot.Type; import org.eclipse.ocl.pivot.TypedElement; import org.eclipse.ocl.pivot.VoidType; import org.eclipse.ocl.pivot.internal.manager.PivotMetamodelManager; import org.eclipse.ocl.pivot.internal.utilities.AbstractConversion; import org.eclipse.ocl.pivot.internal.utilities.EnvironmentFactoryInternal; import org.eclipse.ocl.pivot.internal.utilities.PivotConstantsInternal; import org.eclipse.ocl.pivot.internal.utilities.PivotUtilInternal; import org.eclipse.ocl.pivot.util.Visitable; import org.eclipse.ocl.pivot.utilities.ClassUtil; import org.eclipse.ocl.pivot.utilities.PivotConstants; import org.eclipse.ocl.pivot.utilities.PivotUtil; import org.eclipse.ocl.pivot.values.Unlimited; import org.eclipse.ocl.xtext.base.as2cs.AS2CS.Factory; import org.eclipse.ocl.xtext.base.utilities.BaseCSResource; import org.eclipse.ocl.xtext.basecs.AnnotationCS; import org.eclipse.ocl.xtext.basecs.BaseCSFactory; import org.eclipse.ocl.xtext.basecs.BaseCSPackage; import org.eclipse.ocl.xtext.basecs.ClassCS; import org.eclipse.ocl.xtext.basecs.ConstraintCS; import org.eclipse.ocl.xtext.basecs.DetailCS; import org.eclipse.ocl.xtext.basecs.ElementCS; import org.eclipse.ocl.xtext.basecs.ImportCS; import org.eclipse.ocl.xtext.basecs.ModelElementCS; import org.eclipse.ocl.xtext.basecs.MultiplicityBoundsCS; import org.eclipse.ocl.xtext.basecs.MultiplicityStringCS; import org.eclipse.ocl.xtext.basecs.NamedElementCS; import org.eclipse.ocl.xtext.basecs.PackageCS; import org.eclipse.ocl.xtext.basecs.PathElementCS; import org.eclipse.ocl.xtext.basecs.PathElementWithURICS; import org.eclipse.ocl.xtext.basecs.PathNameCS; import org.eclipse.ocl.xtext.basecs.RootCS; import org.eclipse.ocl.xtext.basecs.StructuralFeatureCS; import org.eclipse.ocl.xtext.basecs.TemplateBindingCS; import org.eclipse.ocl.xtext.basecs.TemplateSignatureCS; import org.eclipse.ocl.xtext.basecs.TypedElementCS; import org.eclipse.ocl.xtext.basecs.TypedRefCS; import org.eclipse.ocl.xtext.basecs.TypedTypeRefCS; public class AS2CSConversion extends AbstractConversion implements PivotConstantsInternal { private static final Logger logger = Logger.getLogger(AS2CSConversion.class); protected final @NonNull AS2CS converter; protected final @NonNull BaseDeclarationVisitor defaultDeclarationVisitor; protected final @NonNull BaseReferenceVisitor defaultReferenceVisitor; private org.eclipse.ocl.pivot.Class scope = null; private final @NonNull Map<EClass, BaseDeclarationVisitor> declarationVisitorMap = new HashMap<EClass, BaseDeclarationVisitor>(); private final @NonNull Map<EClass, BaseReferenceVisitor> referenceVisitorMap = new HashMap<EClass, BaseReferenceVisitor>(); private Map<Namespace, List<String>> importedNamespaces = null; /** * The CS Resource currently being converted. */ private @Nullable BaseCSResource csResource = null;; public AS2CSConversion(@NonNull AS2CS converter) { super(converter.getEnvironmentFactory()); this.converter = converter; this.defaultDeclarationVisitor = converter.createDefaultDeclarationVisitor(this); this.defaultReferenceVisitor = converter.createDefaultReferenceVisitor(this); } protected void addBooleanQualifier(@NonNull List<String> qualifiers, @NonNull DetailCS csDetail, @NonNull String csString) { EList<String> values = csDetail.getValues(); if ((values.size() == 1) && Boolean.valueOf(values.get(0))) { qualifiers.add(csString); } else { qualifiers.add("!" + csString); } } public void createImports(@NonNull RootCS documentCS, @NonNull Map<Namespace, List<String>> importedNamespaces) { BaseCSResource csResource = (BaseCSResource) ClassUtil.nonNullState(documentCS.eResource()); AliasAnalysis.dispose(csResource); // Force reanalysis EnvironmentFactoryInternal environmentFactory = PivotUtilInternal.findEnvironmentFactory(csResource); if (environmentFactory == null) { throw new IllegalStateException("No EnvironmentFactory"); } PivotMetamodelManager metamodelManager = environmentFactory.getMetamodelManager(); AliasAnalysis aliasAnalysis = null; URI csURI = csResource.getURI(); List<ImportCS> imports = new ArrayList<ImportCS>(); for (Namespace importedNamespace : importedNamespaces.keySet()) { if (importedNamespace != null) { if (importedNamespace instanceof org.eclipse.ocl.pivot.Package){ Package pivotPackage = metamodelManager.getCompletePackage((org.eclipse.ocl.pivot.Package)importedNamespace).getPrimaryPackage(); // ModelElementCS csElement = createMap.get(importedPackage); // if ((csElement != null) && (csElement.eResource() == xtextResource)) { // continue; // Don't import defined packages // } if (metamodelManager.getLibraries().contains(pivotPackage)) { continue; } } List<String> aliases = importedNamespaces.get(importedNamespace); if ((aliases == null) || aliases.isEmpty()) { if (aliasAnalysis == null) { aliasAnalysis = AliasAnalysis.getAdapter(csResource, environmentFactory); } String alias = aliasAnalysis.getAlias(importedNamespace, null); aliases = Collections.singletonList(alias); } EObject eObject = importedNamespace.getESObject(); String importURI = null; if (eObject instanceof EPackage) { EPackage ePackage = (EPackage)eObject; Resource resource = ePackage.eResource(); if (ClassUtil.isRegistered(resource)) { importURI = ePackage.getNsURI(); } } if (importURI == null) { URI fullURI = EcoreUtil.getURI(eObject != null ? eObject : importedNamespace); URI deresolvedURI = fullURI.deresolve(csURI, true, true, false); importURI = deresolvedURI.toString(); } for (String alias : aliases) { ImportCS importCS = BaseCSFactory.eINSTANCE.createImportCS(); importCS.setName(alias); PathNameCS csPathName = BaseCSFactory.eINSTANCE.createPathNameCS(); importCS.setOwnedPathName(csPathName); List<PathElementCS> csPath = csPathName.getOwnedPathElements(); PathElementWithURICS csSimpleRef = BaseCSFactory.eINSTANCE.createPathElementWithURICS(); csPath.add(csSimpleRef); csSimpleRef.setReferredElement(importedNamespace); csSimpleRef.setUri(importURI); importCS.setPivot(importedNamespace); imports.add(importCS); } } } if (aliasAnalysis != null) { aliasAnalysis.dispose(); } aliasAnalysis = AliasAnalysis.getAdapter(csResource, metamodelManager.getEnvironmentFactory()); for (ImportCS csImport : imports) { Namespace namespace = csImport.getReferredNamespace(); String alias = csImport.getName(); if ((namespace != null) && (alias == null)) { alias = aliasAnalysis.getAlias(namespace, null); if (alias == null) { String hint = null; if (namespace instanceof org.eclipse.ocl.pivot.Package) { hint = ((org.eclipse.ocl.pivot.Package)namespace).getNsPrefix(); } if (hint == null) { String name = namespace.getName(); if (name.length() > 0) { hint = name.substring(0, 1).toLowerCase() + name.substring(1); } } if (hint != null) { alias = aliasAnalysis.getAlias(namespace, hint); } } if (alias != null) { csImport.setName(alias); } } } Collections.sort(imports, new Comparator<ImportCS>() { @Override public int compare(ImportCS o1, ImportCS o2) { Namespace ns1 = o1.getReferredNamespace(); Namespace ns2 = o2.getReferredNamespace(); int d1 = PivotUtil.getContainmentDepth(ns1); int d2 = PivotUtil.getContainmentDepth(ns2); if (d1 != d2) { return d1 - d2; } String n1 = o1.getName(); String n2 = o2.getName(); return n1.compareTo(n2); } }); documentCS.getOwnedImports().addAll(imports); } public @Nullable BaseCSResource getCSResource() { return csResource; } public @NonNull AS2CS getConverter() { return converter; } public @Nullable BaseDeclarationVisitor getDeclarationVisitor(@NonNull EClass eClass) { BaseDeclarationVisitor declarationVisitor = declarationVisitorMap.get(eClass); if ((declarationVisitor == null) && !declarationVisitorMap.containsKey(eClass)) { Factory factory = converter.getFactory(eClass); if (factory != null) { declarationVisitor = factory.createDeclarationVisitor(this); } else { declarationVisitor = defaultDeclarationVisitor; } declarationVisitorMap.put(eClass, declarationVisitor); } return declarationVisitor; } public @Nullable BaseReferenceVisitor getReferenceVisitor(@NonNull EClass eClass, @Nullable Namespace scope) { if (scope == null) { BaseReferenceVisitor referenceVisitor = referenceVisitorMap.get(eClass); if ((referenceVisitor == null) && !referenceVisitorMap.containsKey(eClass)) { Factory factory = converter.getFactory(eClass); if (factory != null) { referenceVisitor = factory.createReferenceVisitor(this, null); } else { referenceVisitor = defaultReferenceVisitor; } referenceVisitorMap.put(eClass, referenceVisitor); } return referenceVisitor; } else { Factory factory = converter.getFactory(eClass); if (factory != null) { return factory.createReferenceVisitor(this, scope); } else { return defaultReferenceVisitor; } } } public org.eclipse.ocl.pivot.Class getScope() { return scope; } protected List<TemplateBindingCS> getTemplateBindings(ElementCS csElement) { List<TemplateBindingCS> csTemplateBindings; // EObject container = csElement.eContainer(); // if (container instanceof ElementCS) { // csTemplateBindings = getTemplateBindings((ElementCS) container); // } // else { csTemplateBindings = new ArrayList<TemplateBindingCS>(); // } if (csElement instanceof TypedTypeRefCS) { TypedTypeRefCS csTemplateableElement = (TypedTypeRefCS)csElement; TemplateBindingCS csTemplateBinding = csTemplateableElement.getOwnedBinding(); if (csTemplateBinding != null) { csTemplateBindings.add(csTemplateBinding); } } return csTemplateBindings; } public void importNamespace(@NonNull Namespace importNamespace, @Nullable String alias) { Namespace primaryNamespace = metamodelManager.getPrimaryElement(importNamespace); List<String> aliases = importedNamespaces.get(primaryNamespace); if (aliases == null) { aliases = new ArrayList<String>(); importedNamespaces.put(primaryNamespace, aliases); } if ((alias != null) && !aliases.contains(alias)) { aliases.add(alias); } } protected <@NonNull T extends ClassCS> T refreshClassifier(@NonNull Class<T> csClass, /*@NonNull*/ EClass csEClass, org.eclipse.ocl.pivot.@NonNull Class object) { T csElement = refreshNamedElement(csClass, csEClass, object); List<ConstraintCS> csInvariants = visitDeclarations(ConstraintCS.class, object.getOwnedInvariants(), null); for (ConstraintCS csInvariant : csInvariants) { csInvariant.setStereotype(PivotConstants.INVARIANT_NAME); } refreshList(csElement.getOwnedConstraints(), csInvariants); TemplateSignature ownedTemplateSignature = object.getOwnedSignature(); if (ownedTemplateSignature != null) { csElement.setOwnedSignature(visitDeclaration(TemplateSignatureCS.class, ownedTemplateSignature)); } if (object.eIsSet(PivotPackage.Literals.CLASS__INSTANCE_CLASS_NAME)) { csElement.setInstanceClassName(object.getInstanceClassName()); } else { csElement.eUnset(BaseCSPackage.Literals.CLASS_CS__INSTANCE_CLASS_NAME); } return csElement; } public <@NonNull T extends ModelElementCS> T refreshElement(@NonNull Class<T> csClass, /*@NonNull*/ EClass csEClass, @NonNull Element object) { assert csClass == csEClass.getInstanceClass(); EFactory eFactoryInstance = csEClass.getEPackage().getEFactoryInstance(); ModelElementCS csElement = (ModelElementCS) eFactoryInstance.create(csEClass); if (!csClass.isAssignableFrom(csElement.getClass())) { throw new ClassCastException(); } csElement.setPivot(object); @SuppressWarnings("unchecked") T castElement = (T) csElement; return castElement; } public <@NonNull T extends NamedElementCS> T refreshNamedElement(@NonNull Class<T> csClass, /*@NonNull */EClass csEClass, @NonNull NamedElement object) { return refreshNamedElement(csClass, csEClass, object, "«null»"); } public <@NonNull T extends NamedElementCS> T refreshNamedElement(@NonNull Class<T> csClass, /*@NonNull */EClass csEClass, @NonNull NamedElement object, @Nullable String replacementNameForNull) { T csElement = refreshElement(csClass, csEClass, object); String name = object.getName(); if (name == null) { name = replacementNameForNull; } csElement.setName(name); refreshList(csElement.getOwnedAnnotations(), visitDeclarations(AnnotationCS.class, object.getOwnedAnnotations(), null)); return csElement; } /** * Assign a sequence of one or more path elements to csPathName that identify element with respect * to scope. * <br> * For example A::B::C::D::E with respect to A::B::C::X::Y is D::E. * <br> * Validation is performed to check that the shortened name resolves to the same * element. * <br> * For example if there is also an A::B::C::X::D::E, the scope is shortened to A::B so * that the result is C::D::E. */ public void refreshPathName(@NonNull PathNameCS csPathName, @NonNull Element element, @Nullable Namespace scope) {//, @Nullable Resource csResource) { Namespace safeScope = scope; Element primaryElement = metamodelManager.getPrimaryElement(element); if ((safeScope != null) && (primaryElement instanceof Type)) { String name = ((Type)primaryElement).getName(); for (EObject eObject = safeScope; eObject != null; eObject = eObject.eContainer()) { if (eObject instanceof Namespace) { safeScope = (Namespace) eObject; } if (eObject instanceof org.eclipse.ocl.pivot.Package) { CompletePackage completePackage = metamodelManager.getCompletePackage((org.eclipse.ocl.pivot.Package)eObject); org.eclipse.ocl.pivot.Class memberType = completePackage.getMemberType(name); if (memberType == primaryElement) { if ((eObject != scope) && (eObject != PivotUtil.getContainingPackage(scope))) { eObject = eObject.eContainer(); // If eObject is needed in path, optional scope is its container } if (eObject instanceof Namespace) { safeScope = (Namespace) eObject; } break; } } } } List<PathElementCS> csPath = csPathName.getOwnedPathElements(); csPath.clear(); // FIXME re-use PathElementCS csSimpleRef = BaseCSFactory.eINSTANCE.createPathElementCS(); csPath.add(csSimpleRef); csSimpleRef.setReferredElement(primaryElement); BaseCSResource csResource2 = this.csResource; if ((csResource2 == null) || (csResource2.isPathable(primaryElement) == null)) { return; } for (EObject eContainer = primaryElement.eContainer(); eContainer instanceof Element; eContainer = eContainer.eContainer()) { if (eContainer instanceof Model) { return; // Skip root package } for (EObject aScope = safeScope; aScope != null; aScope = aScope.eContainer()) { if (metamodelManager.getPrimaryElement(aScope) == metamodelManager.getPrimaryElement(eContainer)) { // If element ancestor is scope or an ancestor return; // no need for further qualification } } csSimpleRef = BaseCSFactory.eINSTANCE.createPathElementCS(); csPath.add(0, csSimpleRef); csSimpleRef.setReferredElement((Element) eContainer); } } public void refreshQualifiers(List<String> qualifiers, String string, boolean polarity) { for (String qualifier : qualifiers) { if (qualifier.equals(string)) { if (!polarity) { qualifiers.remove(qualifier); } return; } } if (polarity) { qualifiers.add(string); } } public void refreshQualifiers(List<String> qualifiers, String trueString, String falseString, Boolean polarity) { boolean isFalse = false; boolean isTrue = false; for (String qualifier : qualifiers) { if (qualifier.equals(trueString)) { if (isTrue || (polarity != Boolean.TRUE)) { qualifiers.remove(qualifier); } isTrue = true; } if (qualifier.equals(falseString)) { if (isTrue || (polarity != Boolean.FALSE)) { qualifiers.remove(qualifier); } isFalse = true; } } if (polarity == Boolean.TRUE) { if (!isTrue) { qualifiers.add(trueString); } } else if (polarity == Boolean.FALSE) { if (!isFalse) { qualifiers.add(falseString); } } } public <@NonNull T extends StructuralFeatureCS> T refreshStructuralFeature(@NonNull Class<T> csClass, /*@NonNull */EClass csEClass, @NonNull Property object) { T csElement = refreshTypedElement(csClass, csEClass, object); refreshQualifiers(csElement.getQualifiers(), "derived", object.isIsDerived()); refreshQualifiers(csElement.getQualifiers(), "readonly", object.isIsReadOnly()); refreshQualifiers(csElement.getQualifiers(), "static", object.isIsStatic()); refreshQualifiers(csElement.getQualifiers(), "transient", object.isIsTransient()); refreshQualifiers(csElement.getQualifiers(), "unsettable", object.isIsUnsettable()); refreshQualifiers(csElement.getQualifiers(), "volatile", object.isIsVolatile()); csElement.setDefault(object.getDefaultValueString()); return csElement; } public <@NonNull T extends TypedElementCS> T refreshTypedElement(@NonNull Class<T> csClass, /*@NonNull */EClass csEClass, @NonNull TypedElement object) { T csElement = refreshNamedElement(csClass, csEClass, object); final Type type = object.getType(); final Type elementType; if ((type instanceof CollectionType) && (((CollectionType)type).getUnspecializedElement() != standardLibrary.getCollectionType())) { PivotUtil.debugWellContainedness(type); elementType = ((CollectionType)type).getElementType(); } else if (type instanceof VoidType) { elementType = null; } else { elementType = type; } if (elementType != null) { PivotUtil.debugWellContainedness(elementType); TypedRefCS typeRef = visitReference(TypedRefCS.class, elementType, null); csElement.setOwnedType(typeRef); } else { csElement.setOwnedType(null); } TypedRefCS csTypeRef = csElement.getOwnedType(); if (csTypeRef != null) { boolean isNullFree ; int lower; int upper; if ((type instanceof CollectionType) && (((CollectionType)type).getUnspecializedElement() != standardLibrary.getCollectionType())) { CollectionType collectionType = (CollectionType)type; isNullFree = collectionType.isIsNullFree(); lower = collectionType.getLower().intValue(); Number upper2 = collectionType.getUpper(); upper = upper2 instanceof Unlimited ? -1 : upper2.intValue(); List<String> qualifiers = csElement.getQualifiers(); refreshQualifiers(qualifiers, "ordered", "!ordered", collectionType.isOrdered() ? Boolean.TRUE : null); refreshQualifiers(qualifiers, "unique", "!unique", collectionType.isUnique() ? null : Boolean.FALSE); } else { isNullFree = false; lower = object.isIsRequired() ? 1 : 0; upper = 1; } // if ((lower == 0) && (upper == 1)) { // csTypeRef.setOwnedMultiplicity(null); // } // else { String stringValue = null; if (lower == 0) { if (upper == 1) { stringValue = "?"; } else if (upper == -1) { stringValue = "*"; } // else if (upper == -2) { // stringValue = "0..?"; // } } else if (lower == 1) { if (upper == -1) { stringValue = "+"; } } if (stringValue != null) { MultiplicityStringCS csMultiplicity = BaseCSFactory.eINSTANCE.createMultiplicityStringCS(); csMultiplicity.setStringBounds(stringValue); csMultiplicity.setIsNullFree(isNullFree);; csTypeRef.setOwnedMultiplicity(csMultiplicity); } else { MultiplicityBoundsCS csMultiplicity = BaseCSFactory.eINSTANCE.createMultiplicityBoundsCS(); if (lower != 1) { csMultiplicity.setLowerBound(lower); } if (upper != 1) { csMultiplicity.setUpperBound(upper); } csMultiplicity.setIsNullFree(isNullFree);; csTypeRef.setOwnedMultiplicity(csMultiplicity); } // } } return csElement; } public org.eclipse.ocl.pivot.Class setScope(org.eclipse.ocl.pivot.Class object) { org.eclipse.ocl.pivot.Class savedScope = scope; this.scope = object; return savedScope; } /** * Sequence the update passes to make the pivot match the CS. */ public void update(@NonNull BaseCSResource csResource) { this.csResource = csResource; // Map<Resource, Map<Namespace, List<String>>> imports = new HashMap<Resource, Map<Namespace, List<String>>>(); // // Perform the pre-order traversal to create the CS for each declaration. A // separate reference pass is not needed since references are to the pivot model. // importedNamespaces = new HashMap<Namespace, List<String>>(); Resource asResource = converter.getASResource(csResource); if (asResource != null) { List<@NonNull PackageCS> list = visitDeclarations(PackageCS.class, asResource.getContents(), null); refreshList(csResource.getContents(), list); if (importedNamespaces != null) { defaultDeclarationVisitor.postProcess(csResource, importedNamespaces); } // imports.put(csResource, importedNamespaces); } } public <T extends ElementCS> @Nullable T visitDeclaration(@NonNull Class<T> csClass, @Nullable EObject eObject) { if (eObject == null) { return null; } @SuppressWarnings("null") @NonNull EClass eClass = eObject.eClass(); BaseDeclarationVisitor declarationVisitor = getDeclarationVisitor(eClass); if ((declarationVisitor == null) || !(eObject instanceof Visitable)) { logger.warn("Unsupported declaration " + eClass.getName()); return null; } ElementCS csElement = ((Visitable)eObject).accept(declarationVisitor); @SuppressWarnings("unchecked") T castElement = (T) csElement; return castElement; } public <T extends ElementCS, @Nullable V extends EObject> @Nullable List<@NonNull T> visitDeclarationAsList(@NonNull Class<T> csClass, V eObject) { if (eObject == null) { return null; } @Nullable T csElement = visitDeclaration(csClass, eObject); if (csElement == null) { return null; } return Collections.singletonList(csElement); } public @NonNull <T extends ElementCS, V extends EObject> List<T> visitDeclarations(@NonNull Class<T> csClass, /*@NonNull*/ List<V> eObjects, AS2CS.@Nullable Predicate<V> predicate) { assert eObjects != null; List<T> csElements = new ArrayList<T>(); for (V eObject : eObjects) { if ((eObject != null) && ((predicate == null) || predicate.filter(eObject))) { @Nullable T csElement = visitDeclaration(csClass, eObject); if (csElement != null) { csElements.add(csElement); } } } return csElements; } public @Nullable <T extends ElementCS> T visitReference(@NonNull Class<T> csClass, @NonNull EObject eObject, @Nullable Namespace scope) { @SuppressWarnings("null") @NonNull EClass eClass = eObject.eClass(); BaseReferenceVisitor referenceVisitor = getReferenceVisitor(eClass, scope); if ((referenceVisitor == null) || !(eObject instanceof Visitable)) { logger.warn("Unsupported reference " + eObject.eClass().getName()); return null; } ElementCS csElement = ((Visitable)eObject).accept(referenceVisitor); if (csElement == null) { return null; } if (!csClass.isAssignableFrom(csElement.getClass())) { logger.error("CS " + csElement.getClass().getName() + "' element is not a '" + csClass.getName() + "'"); //$NON-NLS-1$ return null; } @SuppressWarnings("unchecked") T castElement = (T) csElement; return castElement; } public @NonNull <T extends ElementCS, V extends EObject> List<T> visitReferences(@NonNull Class<T> csClass, /*@NonNull*/ List<? extends V> eObjects, AS2CS.@Nullable Predicate<V> predicate) { assert eObjects != null; List<T> csElements = new ArrayList<T>(); for (V eObject : eObjects) { if ((eObject != null) && ((predicate == null) || predicate.filter(eObject))) { @Nullable T csElement = visitReference(csClass, eObject, null); if (csElement != null) { csElements.add(csElement); } } } return csElements; } }