/******************************************************************************* * Copyright (c) 2005, 2006 committers of openArchitectureWare 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: * committers of openArchitectureWare - initial API and implementation *******************************************************************************/ package org.eclipse.xtend.expression; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.eclipse.emf.mwe.core.WorkflowContext; import org.eclipse.emf.mwe.core.WorkflowInterruptedException; import org.eclipse.emf.mwe.core.issues.Issues; import org.eclipse.emf.mwe.core.lib.AbstractWorkflowComponent2; import org.eclipse.emf.mwe.core.monitor.ProgressMonitor; import org.eclipse.internal.xtend.expression.ast.SyntaxElement; import org.eclipse.internal.xtend.util.Pair; import org.eclipse.xtend.type.impl.java.JavaBeansMetaModel; import org.eclipse.xtend.typesystem.MetaModel; public abstract class AbstractExpressionsUsingWorkflowComponent extends AbstractWorkflowComponent2 { protected final Log log = LogFactory.getLog(getClass()); protected final List<MetaModel> metaModels = new ArrayList<MetaModel>(); private List<GlobalVarDef> globalVarDefs = new ArrayList<GlobalVarDef>(); private List<GlobalVar> globalVars = new ArrayList<GlobalVar>(); protected final List<String> _advice = new ArrayList<String>(); public void addAdvice(String advice) { for (String singleAdvice : advice.split(",")) { singleAdvice = singleAdvice.trim(); if (singleAdvice.length() == 0) { continue; } if (!_advice.contains(singleAdvice)) { _advice.add(singleAdvice); } } } public void addAdvices(String advice) { addAdvice(advice); } public void addExtensionAdvice(String advice) { addAdvice(advice); } public void addExtensionAdvices(String advice) { addExtensionAdvice(advice); } public void addMetaModel(final MetaModel metaModel) { assert metaModel != null; metaModels.add(metaModel); } public static class GlobalVarDef { private String name; private String value; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getValue() { return value; } public void setValue(String value) { this.value = value; } } public void addGlobalVarDef(GlobalVarDef def) { globalVarDefs.add(def); } public void addGlobalVar(GlobalVar var) { globalVars.add(var); } public static class GlobalVar { private String name; private Object value; public void setName(String name) { this.name = name; } public void setValue(Object value) { this.value = value; } public String getName() { return name; } public Object getValue() { return value; } } protected Map<String, Variable> getGlobalVars(WorkflowContext ctx) { final Map<String, Variable> result = new HashMap<String, Variable>(); if (!globalVarDefs.isEmpty()) { ExecutionContextImpl ec = new ExecutionContextImpl(); for (String slot : ctx.getSlotNames()) { ec = (ExecutionContextImpl) ec.cloneWithVariable(new Variable( slot, ctx.get(slot))); } for (MetaModel mm : metaModels) { ec.registerMetaModel(mm); } final ExpressionFacade ef = new ExpressionFacade(ec); for (GlobalVarDef def : globalVarDefs) { final Object value = ef.evaluate(def.getValue()); result.put(def.getName(), new Variable(def.getName(), value)); } } for (GlobalVar gv : globalVars) { result.put(gv.getName(), new Variable(gv.getName(), gv.getValue())); } return result; } protected VetoableCallback callback; /** * @deprecated Use {@link #setVetoableCallback(VetoableCallback)} instead. */ @Deprecated public void setCallback(Callback callback) { this.callback = new VetoableCallbackAdapter(callback); } public void setVetoableCallback(VetoableCallback callback) { this.callback = callback; } protected ExecutionContextImpl getExecutionContext(final WorkflowContext ctx) { final ExecutionContextImpl executionContext = new ExecutionContextImpl( getResourceManager(), null, new TypeSystemImpl(), new HashMap<String, Variable>(), getGlobalVars(ctx), null, exceptionHandler, null, getNullEvaluationHandler(), null, callback, null, null); for (MetaModel mm : metaModels) { executionContext.registerMetaModel(mm); } return executionContext; } public NullEvaluationHandler getNullEvaluationHandler() { if (exceptionsOnNullEvaluation) return new ExceptionRaisingNullEvaluationHandler(); return null; } @Override protected void checkConfigurationInternal(Issues issues) { if (metaModels.isEmpty()) { log.info("No meta models configured, using JavaBeans as default."); metaModels.add(new JavaBeansMetaModel()); } } private List<Debug> debugExpressions = new ArrayList<Debug>(); public void addDebug(Debug expr) { this.debugExpressions.add(expr); } private boolean dumpContext = false; public void setDumpContext(boolean dumpContext) { this.dumpContext = dumpContext; } public static class Debug { private String expression; private boolean dumpContext = false; public void setDumpContext(boolean dumpContext) { this.dumpContext = dumpContext; } public boolean isDumpContext() { return dumpContext; } public void setExpression(String expression) { this.expression = expression; } public String getExpression() { return expression; } } @Override protected void invokeInternal(WorkflowContext ctx, ProgressMonitor monitor, final Issues issues) { try { if (exceptionHandler == null) { exceptionHandler = new ExceptionHandler() { public void handleRuntimeException(RuntimeException ex, SyntaxElement element, ExecutionContext ctx, Map<String, Object> additionalContextInfo) { issues.addError( AbstractExpressionsUsingWorkflowComponent.this, ex.getMessage(), element); throw ex; } }; } invokeInternal2(ctx, monitor, issues); } catch (EvaluationException e) { if (e.getCause() != null) log.error(e.getMessage(), e.getCause()); log.error("Error in Component" + (getId() == null ? " " : " " + getId()) + " of type " + getClass().getName() + ": \n\t" + "" + toString(e, debugExpressions)); throw new WorkflowInterruptedException(e.getMessage()); } } public String toString(EvaluationException ex, List<Debug> debugEntries) { StringBuffer result = new StringBuffer("EvaluationException : " + ex.getMessage() + "\n"); int widest = 0; for (Pair<SyntaxElement, ExecutionContext> ele : ex .getXtendStackTrace()) { int temp = EvaluationException.getLocationString(ele.getFirst()) .length(); if (temp > widest) { widest = temp; } } String indent = ""; for (int l = 0; l < widest + 7; l++) { indent += " "; } for (int i = 0, x = ex.getXtendStackTrace().size(); i < x; i++) { Pair<SyntaxElement, ExecutionContext> ele = ex.getXtendStackTrace() .get(i); StringBuffer msg = new StringBuffer(EvaluationException .getLocationString(ele.getFirst())); for (int j = msg.length(); j < widest; j++) { msg.append(" "); } if (debugEntries.size() > i && debugEntries.get(i).getExpression() != null) { Debug d = debugEntries.get(i); try { msg.append(" -- debug '").append(d.getExpression()).append( "' = "); msg.append(new ExpressionFacade(ele.getSecond()) .evaluate("let x = " + d.getExpression() + " : x!=null ? x.toString() : 'null'")); } catch (Exception e) { msg.append("Exception : ").append(e.getMessage()); } msg.append("\n"); } if (dumpContext || debugEntries.size() > i && debugEntries.get(i).isDumpContext()) { ExpressionFacade f = new ExpressionFacade(ele.getSecond()); msg.append(" -- context dump : "); Iterator<String> iter = ele.getSecond().getVisibleVariables() .keySet().iterator(); while (iter.hasNext()) { String v = iter.next(); msg.append(v).append(" = ").append( f .evaluate(v + "!=null?" + v + ".toString():'null'")); if (iter.hasNext()) { msg.append(", \n"); } } msg.append("\n"); } // formatting String[] evals = msg.toString().split("\n"); for (int j = 0; j < evals.length; j++) { String string = evals[j]; result.append(string); if (j + 1 < evals.length) { result.append("\n").append(indent); } } result.append("\n"); } return result.toString(); } protected void invokeInternal2(WorkflowContext ctx, ProgressMonitor monitor, Issues issues) { } protected boolean exceptionsOnNullEvaluation = false; protected ExceptionHandler exceptionHandler = null; public void setExceptionsOnNullEvaluation(boolean exceptionsOnNullEvaluation) { this.exceptionsOnNullEvaluation = exceptionsOnNullEvaluation; } public void setExceptionHandler(final ExceptionHandler exceptionHandler) { this.exceptionHandler = exceptionHandler; } private ResourceManager resourceManager; public ResourceManager getResourceManager() { if (resourceManager == null) { resourceManager = new ResourceManagerDefaultImpl(); } return resourceManager; } public void setResourceManager(ResourceManager resourceManager) { this.resourceManager = resourceManager; } }