/*******************************************************************************
* Copyright (c) 2010-2012, Zoltan Ujhelyi, Istvan Rath and Daniel Varro
* 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:
* Zoltan Ujhelyi - initial API and implementation
*******************************************************************************/
package org.eclipse.incquery.patternlanguage.emf.scoping;
import java.util.Collections;
import java.util.List;
import org.apache.log4j.Logger;
import org.eclipse.emf.ecore.EEnum;
import org.eclipse.emf.ecore.EEnumLiteral;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.incquery.patternlanguage.emf.EMFPatternLanguageScopeHelper;
import org.eclipse.incquery.patternlanguage.emf.ResolutionException;
import org.eclipse.incquery.patternlanguage.emf.eMFPatternLanguage.EMFPatternLanguagePackage;
import org.eclipse.incquery.patternlanguage.emf.eMFPatternLanguage.EnumValue;
import org.eclipse.incquery.patternlanguage.emf.eMFPatternLanguage.PackageImport;
import org.eclipse.incquery.patternlanguage.patternLanguage.PathExpressionHead;
import org.eclipse.xtext.conversion.IValueConverterService;
import org.eclipse.xtext.conversion.ValueConverterException;
import org.eclipse.xtext.linking.impl.DefaultLinkingService;
import org.eclipse.xtext.nodemodel.ILeafNode;
import org.eclipse.xtext.nodemodel.INode;
import com.google.inject.Inject;
public class EMFPatternLanguageLinkingService extends DefaultLinkingService {
@Inject
private Logger logger;
@Inject
private IValueConverterService valueConverterService;
@Inject
private IMetamodelProvider metamodelProvider;
@Override
public List<EObject> getLinkedObjects(EObject context, EReference ref, INode node) {
if (ref == EMFPatternLanguagePackage.eINSTANCE.getPackageImport_EPackage() && context instanceof PackageImport
&& node instanceof ILeafNode) {
return getPackage((PackageImport) context, (ILeafNode) node);
} else if (ref == EMFPatternLanguagePackage.eINSTANCE.getEnumValue_Literal() && context instanceof EnumValue
&& node instanceof ILeafNode) {
return getEnumLiteral((EnumValue) context, node);
}
return super.getLinkedObjects(context, ref, node);
}
private List<EObject> getEnumLiteral(EnumValue value, INode node) {
try {
EEnum type = null;
if (value.getEnumeration() != null) {
type = value.getEnumeration();
} else if (value.eContainer() instanceof PathExpressionHead) {
type = EMFPatternLanguageScopeHelper.calculateEnumerationType(getExpressionHead(value.eContainer()));
} else {
return Collections.emptyList();
}
String typename = ((ILeafNode) node).getText();
EEnumLiteral literal = type.getEEnumLiteralByLiteral(typename);
if (literal == null) {
literal = type.getEEnumLiteral(typename);
}
if (literal != null) {
return Collections.<EObject> singletonList(literal);
} else {
return Collections.emptyList();
}
} catch (ResolutionException e) {
return Collections.emptyList();
}
}
private PathExpressionHead getExpressionHead(EObject obj) {
if (obj instanceof PathExpressionHead) {
return (PathExpressionHead) obj;
} else if (obj.eContainer() != null) {
return getExpressionHead(obj.eContainer());
} else {
return null;
}
}
private List<EObject> getPackage(PackageImport context, ILeafNode text) {
String nsUri = getMetamodelNsURI(text);
if (nsUri == null) {
return Collections.emptyList();
}
EPackage pack = metamodelProvider.loadEPackage(nsUri, context.eResource().getResourceSet());
if (pack != null) {
return Collections.<EObject> singletonList(pack);
}
return Collections.emptyList();
}
private String getMetamodelNsURI(ILeafNode text) {
try {
return (String) valueConverterService.toValue(text.getText(),
getLinkingHelper().getRuleNameFrom(text.getGrammarElement()), text);
} catch (ValueConverterException e) {
logger.debug("Exception on leaf '" + text.getText() + "'", e);
return null;
}
}
}