blob: 214b670b4b76e08908e5aca6fae8fa5b7662fd20 [file] [log] [blame]
/*********************************************************************
* Copyright (c) 2008 The University of York.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
package org.eclipse.epsilon.picto;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import org.eclipse.epsilon.common.module.ModuleElement;
import org.eclipse.epsilon.common.parse.AST;
import org.eclipse.epsilon.egl.EglTemplate;
import org.eclipse.epsilon.egl.EglTemplateFactory;
import org.eclipse.epsilon.egl.EgxModule;
import org.eclipse.epsilon.egl.dom.GenerationRule;
import org.eclipse.epsilon.egl.execute.context.IEgxContext;
import org.eclipse.epsilon.eol.dom.Parameter;
import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
import org.eclipse.epsilon.eol.execute.ExecutorFactory;
import org.eclipse.epsilon.eol.execute.context.FrameStack;
import org.eclipse.epsilon.eol.execute.context.FrameType;
import org.eclipse.epsilon.eol.execute.context.IEolContext;
import org.eclipse.epsilon.eol.execute.context.Variable;
import org.eclipse.epsilon.eol.types.EolAnyType;
import org.eclipse.epsilon.pinset.DatasetRule;
import org.eclipse.epsilon.pinset.PinsetModule;
public class LazyEgxModule extends EgxModule {
public LazyEgxModule() {
super();
}
public LazyEgxModule(EglTemplateFactory templateFactory) {
super(templateFactory);
}
@Override
public ModuleElement adapt(AST cst, ModuleElement parentAst) {
ModuleElement ast = super.adapt(cst, parentAst);
if (ast instanceof GenerationRule) return new LazyGenerationRule();
else return ast;
}
@SuppressWarnings("unchecked")
@Override
protected Object processRules() throws EolRuntimeException {
IEgxContext context = getContext();
ExecutorFactory ef = context.getExecutorFactory();
context.getOperationContributorRegistry().add(new PictoOperationContributor(this));
Collection<? extends GenerationRule> rules = getGenerationRules();
Collection<LazyGenerationRuleContentPromise> promises = new ArrayList<>(rules.size());
for (GenerationRule rule : rules) {
if (!rule.isLazy(context)) {
promises.addAll((Collection<? extends LazyGenerationRuleContentPromise>) ef.execute(rule, context));
}
}
return promises;
}
public class LazyGenerationRule extends GenerationRule {
@Override
public Object execute(IEolContext context_, Object element) throws EolRuntimeException {
IEgxContext context = (IEgxContext) context_;
FrameStack frameStack = context.getFrameStack();
if (sourceParameter != null) {
frameStack.enterLocal(FrameType.PROTECTED, this, Variable.createReadOnlyVariable(sourceParameter.getName(), element));
}
else {
frameStack.enterLocal(FrameType.PROTECTED, this);
}
if (guardBlock != null && !guardBlock.execute(context, false)) {
frameStack.leaveLocal(this);
return null;
}
if (preBlock != null) {
preBlock.execute(context, false);
}
final String templateName = (templateBlock == null) ? null : templateBlock.execute(context, false);
final EglTemplateFactory templateFactory = context.getTemplateFactory();
final Map<URI, EglTemplate> templateCache = context.getTemplateCache();
List<Variable> variables = new ArrayList<>();
URI templateUri = null;
if (templateName != null) {
templateUri = templateFactory.resolveTemplate(templateName);
}
if (sourceParameter != null) {
variables.add(Variable.createReadOnlyVariable(sourceParameter.getName(), element));
}
if (parametersBlock != null) {
for (Map.Entry<String, ?> entry : parametersBlock.execute(context, false).entrySet()) {
variables.add(new Variable(entry.getKey(), entry.getValue(), EolAnyType.Instance, false));
}
}
frameStack.leaveLocal(this);
return new LazyGenerationRuleContentPromise(templateFactory, templateCache, templateUri, variables);
}
@Override
public Object execute(IEolContext context) throws EolRuntimeException {
Collection<LazyGenerationRuleContentPromise> promises = new ArrayList<>();
ExecutorFactory ef = context.getExecutorFactory();
for (Object element : getAllElements(context)) {
Object result = ef.execute(this, context, element);
if (result instanceof LazyGenerationRuleContentPromise) {
promises.add((LazyGenerationRuleContentPromise) result);
}
}
return promises;
}
public Parameter getSourceParameter() {
return sourceParameter;
}
}
public class LazyGenerationRuleContentPromise implements ContentPromise {
protected EglTemplateFactory templateFactory;
protected Map<URI, EglTemplate> templateCache;
protected URI templateUri;
protected Collection<Variable> variables;
protected LazyGenerationRuleContentPromise() {}
public LazyGenerationRuleContentPromise(EglTemplateFactory templateFactory,
Map<URI, EglTemplate> templateCache,
URI templateUri, Collection<Variable> variables) {
this.templateFactory = templateFactory;
this.templateCache = templateCache;
this.templateUri = templateUri;
this.variables = variables;
}
public Collection<Variable> getVariables() {
return variables;
}
@Override
public String getContent() throws Exception {
if (templateUri == null) return "";
if (templateUri.toString().endsWith(".pinset")) {
PinsetModule module = new PinsetModule();
module.setContext(context);
module.persistDatasets(false);
module.parse(templateUri);
String ruleName = null;
for (Variable variable : variables) {
if (variable.getName().equalsIgnoreCase("pinsetrule")) {
ruleName = "" + variable.getValue();
break;
}
}
DatasetRule rule = null;
if (ruleName != null) {
rule = module.getDatasetRule(ruleName);
if (rule == null) {
throw new RuntimeException("Pinset rule \"" + ruleName + "\" not found");
}
}
else {
rule = module.getDatasetRules().get(0);
}
context.getFrameStack().enterLocal(FrameType.PROTECTED, module,
variables.toArray(new Variable[variables.size()]));
module.preExecution();
rule.execute(module.getContext());
context.getFrameStack().leaveLocal(module);
String content = rule.getDataset().toString(module.getSeparator());
rule.dispose();
return content;
}
EglTemplate template = null;
if (templateCache == null || (template = templateCache.get(templateUri)) == null) {
template = templateFactory.load(templateUri);
if (templateCache != null) {
templateCache.put(templateUri, template);
}
}
for (Variable variable : variables) {
template.populate(variable.getName(), variable.getValue());
}
String result = template.process();
template.reset();
return result;
}
}
}