/**
* Copyright (c) 2016 itemis AG - All rights Reserved
* Unauthorized copying of this file, via any medium is strictly prohibited
*
* Contributors:
* Andreas Muelder - itemis AG
* Thomas Kutz - itemis AG
*
*/
package org.yakindu.sct.model.stext.scoping;
import static java.util.Collections.singletonList;
import java.util.List;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.xtext.EcoreUtil2;
import org.eclipse.xtext.naming.QualifiedName;
import org.eclipse.xtext.resource.ISelectable;
import org.eclipse.xtext.scoping.IScope;
import org.eclipse.xtext.scoping.impl.ImportNormalizer;
import org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider;
import org.yakindu.base.types.Package;
import org.yakindu.sct.model.sgraph.SGraphPackage;
import org.yakindu.sct.model.sgraph.Scope;
import org.yakindu.sct.model.sgraph.Statechart;
import org.yakindu.sct.model.sgraph.util.ContextElementAdapter;
import org.yakindu.sct.model.stext.stext.ImportScope;
import org.yakindu.sct.model.stext.stext.StateSpecification;
import org.yakindu.sct.model.stext.stext.TransitionSpecification;
import com.google.common.collect.Lists;
/**
*
* @author thomas kutz
*
*/
public class StextImportAwareScopeProvider extends ImportedNamespaceAwareLocalScopeProvider {
@Override
public IScope getScope(EObject context, EReference reference) {
if (context == null)
throw new NullPointerException("context");
IScope result = null;
if (context instanceof ImportScope) {
result = getResourceScope(context.eResource(), reference);
} else if (context.eContainer() != null) {
result = getScope(context.eContainer(), reference);
} else {
result = getResourceScope(context.eResource(), reference);
}
return getLocalElementsScope(result, context, reference);
}
@Override
protected List<ImportNormalizer> internalGetImportedNamespaceResolvers(final EObject context, boolean ignoreCase) {
List<ImportNormalizer> importedNamespaceResolvers = Lists.newArrayList();
List<ImportScope> importScopes = null;
if (context instanceof StateSpecification || context instanceof TransitionSpecification) {
importScopes = EcoreUtil2.getAllContentsOfType(getStatechart(context), ImportScope.class);
} else {
importScopes = EcoreUtil2.getAllContentsOfType(context, ImportScope.class);
}
for (ImportScope scope : importScopes) {
importedNamespaceResolvers.addAll(createNamespaceResolver(scope, ignoreCase));
}
return importedNamespaceResolvers;
}
@Override
protected ImportNormalizer doCreateImportNormalizer(QualifiedName importedNamespace, boolean wildcard,
boolean ignoreCase) {
// all imports should be treated as if they had a wild card
return new ImportNormalizer(importedNamespace, true, ignoreCase);
}
protected List<ImportNormalizer> createNamespaceResolver(Scope scope, boolean ignoreCase) {
List<ImportNormalizer> importedNamespaceResolvers = Lists.newArrayList();
ImportScope importScope = (ImportScope) scope;
for (org.yakindu.base.types.Package child : importScope.getImports()) {
String value = getImportedNamespace(child);
ImportNormalizer resolver = createImportedNamespaceResolver(value, ignoreCase);
if (resolver != null)
importedNamespaceResolvers.add(resolver);
}
return importedNamespaceResolvers;
}
protected IScope getLocalElementsScope(IScope parent, final EObject context, final EReference reference) {
IScope result = parent;
ISelectable allDescriptions = getAllDescriptions(context.eResource());
QualifiedName name = getQualifiedNameOfLocalElement(context);
boolean ignoreCase = isIgnoreCase(reference);
final List<ImportNormalizer> namespaceResolvers = getImportedNamespaceResolvers(context, ignoreCase);
if (!namespaceResolvers.isEmpty()) {
if (isRelativeImport() && name != null && !name.isEmpty()) {
ImportNormalizer localNormalizer = doCreateImportNormalizer(name, true, ignoreCase);
result = createImportScope(result, singletonList(localNormalizer), allDescriptions,
reference.getEReferenceType(), isIgnoreCase(reference));
}
result = createImportScope(result, namespaceResolvers, null, reference.getEReferenceType(),
isIgnoreCase(reference));
}
if (name != null) {
ImportNormalizer localNormalizer = doCreateImportNormalizer(name, true, ignoreCase);
result = createImportScope(result, singletonList(localNormalizer), allDescriptions,
reference.getEReferenceType(), isIgnoreCase(reference));
}
return result;
}
@Override
protected String getImportedNamespace(EObject object) {
if (object instanceof Package)
return ((Package) object).getName();
return super.getImportedNamespace(object);
}
protected Statechart getStatechart(EObject context) {
final ContextElementAdapter provider = (ContextElementAdapter) EcoreUtil.getExistingAdapter(context.eResource(),
ContextElementAdapter.class);
if (provider == null) {
return EcoreUtil2.getContainerOfType(context, Statechart.class);
} else {
return (Statechart) EcoreUtil.getObjectByType(provider.getElement().eResource().getContents(),
SGraphPackage.Literals.STATECHART);
}
}
}