blob: bfbab51a8c93beecbf7459c7e5a5e99dcfa5c45d [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2020, 2021 Obeo.
* 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:
* Obeo - initial API and implementation
*******************************************************************************/
package org.eclipse.acceleo.aql.parser;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.eclipse.acceleo.Import;
import org.eclipse.acceleo.Module;
import org.eclipse.acceleo.ModuleElement;
import org.eclipse.acceleo.ModuleReference;
import org.eclipse.acceleo.Query;
import org.eclipse.acceleo.Template;
import org.eclipse.acceleo.aql.evaluation.AcceleoEvaluator;
import org.eclipse.acceleo.aql.evaluation.QueryService;
import org.eclipse.acceleo.aql.evaluation.TemplateService;
import org.eclipse.acceleo.query.runtime.IService;
import org.eclipse.acceleo.query.runtime.impl.namespace.AbstractLoader;
import org.eclipse.acceleo.query.runtime.impl.namespace.Position;
import org.eclipse.acceleo.query.runtime.impl.namespace.Range;
import org.eclipse.acceleo.query.runtime.impl.namespace.SourceLocation;
import org.eclipse.acceleo.query.runtime.namespace.IQualifiedNameLookupEngine;
import org.eclipse.acceleo.query.runtime.namespace.IQualifiedNameResolver;
import org.eclipse.acceleo.query.runtime.namespace.ISourceLocation;
import org.eclipse.acceleo.query.runtime.namespace.ISourceLocation.IPosition;
import org.eclipse.acceleo.query.runtime.namespace.ISourceLocation.IRange;
/**
* Loader for {@link Module}.
*
* @author <a href="mailto:yvan.lussaud@obeo.fr">Yvan Lussaud</a>
*/
public class ModuleLoader extends AbstractLoader {
/**
* The {@link AcceleoEvaluator}.
*/
private final AcceleoEvaluator evaluator;
/**
* The {@link AcceleoParser}.
*/
private AcceleoParser parser;
/**
* Constructor.
*
* @param parser
* the {@link AcceleoParser}
* @param evaluator
* the {@link AcceleoEvaluator}
*/
public ModuleLoader(AcceleoParser parser, AcceleoEvaluator evaluator) {
super(AcceleoParser.QUALIFIER_SEPARATOR, AcceleoParser.MODULE_FILE_EXTENSION,
AcceleoParser.MODULE_FILE_EXTENSION);
this.parser = parser;
this.evaluator = evaluator;
}
@Override
public Object load(IQualifiedNameResolver resolver, String qualifiedName) {
Module res;
// TODO use the proper charset (using the comment on first line)
try (InputStream is = resolver.getInputStream(resourceName(qualifiedName))) {
if (is != null) {
res = parser.parse(is, StandardCharsets.UTF_8, qualifiedName).getModule();
} else {
res = null;
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
res = null;
}
return res;
}
@Override
public boolean canHandle(Object object) {
return object instanceof Module;
}
@Override
public Set<IService<?>> getServices(IQualifiedNameLookupEngine lookupEngine, Object object,
String contextQualifiedName) {
final Set<IService<?>> res = new LinkedHashSet<IService<?>>();
final Module module = (Module)object;
for (ModuleElement element : module.getModuleElements()) {
if (element instanceof Template) {
res.add(new TemplateService((Template)element, evaluator, lookupEngine,
contextQualifiedName));
} else if (element instanceof Query) {
res.add(new QueryService((Query)element, evaluator, lookupEngine, contextQualifiedName));
}
}
return res;
}
@Override
public List<String> getImports(Object object) {
final List<String> res = new ArrayList<String>();
final Module module = (Module)object;
for (Import imp : module.getImports()) {
final ModuleReference moduleRef = imp.getModule();
if (moduleRef != null && moduleRef.getQualifiedName() != null) {
res.add(moduleRef.getQualifiedName());
}
}
return res;
}
@Override
public String getExtends(Object object) {
final String res;
final Module module = (Module)object;
final ModuleReference ext = module.getExtends();
if (ext != null) {
res = ext.getQualifiedName();
} else {
res = null;
}
return res;
}
@Override
public ISourceLocation getSourceLocation(IQualifiedNameResolver resolver, IService<?> service) {
final ISourceLocation res;
if (service.getOrigin() instanceof ModuleElement) {
final ModuleElement moduleElement = (ModuleElement)service.getOrigin();
if (moduleElement.eContainer() instanceof Module) {
final Module module = (Module)moduleElement.eContainer();
if (module.eResource().getURI() != null) {
final String qualifiedName = module.eResource().getURI().toString().substring(
AcceleoParser.ACCELEOENV_URI_PROTOCOL.length());
final URL sourceURL = resolver.getSourceURL(qualifiedName);
final int identifierStartLine = module.getAst().getIdentifierStartLine(moduleElement);
final int identifierStartColumn = module.getAst().getIdentifierStartColumn(moduleElement);
final int identifierStartPosition = module.getAst().getIdentifierStartPosition(
moduleElement);
final IPosition identifierStart = new Position(identifierStartLine, identifierStartColumn,
identifierStartPosition);
final int identifierEndLine = module.getAst().getIdentifierEndLine(moduleElement);
final int identifierEndColumn = module.getAst().getIdentifierEndColumn(moduleElement);
final int identifierEndPosition = module.getAst().getIdentifierEndPosition(moduleElement);
final IPosition identifierEnd = new Position(identifierEndLine, identifierEndColumn,
identifierEndPosition);
final IRange identifierRange = new Range(identifierStart, identifierEnd);
final int startLine = module.getAst().getStartLine(moduleElement);
final int startColumn = module.getAst().getStartColumn(moduleElement);
final int startPosition = module.getAst().getStartPosition(moduleElement);
final IPosition start = new Position(startLine, startColumn, startPosition);
final int endLine = module.getAst().getEndLine(moduleElement);
final int endColumn = module.getAst().getEndColumn(moduleElement);
final int endPosition = module.getAst().getEndPosition(moduleElement);
final IPosition end = new Position(endLine, endColumn, endPosition);
final IRange range = new Range(start, end);
res = new SourceLocation(sourceURL, identifierRange, range);
} else {
res = null;
}
} else {
res = null;
}
} else {
res = null;
}
return res;
}
}