/*******************************************************************************
* Copyright (c) 2005, 2007 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.check;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
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.monitor.ProgressMonitor;
import org.eclipse.xtend.expression.AbstractExpressionsUsingWorkflowComponent;
import org.eclipse.xtend.expression.ExecutionContext;
import org.eclipse.xtend.expression.ExecutionContextImpl;
import org.eclipse.xtend.expression.ExpressionFacade;
public class CheckComponent extends AbstractExpressionsUsingWorkflowComponent {
private static final String COMPONENT_NAME = "Check component";
private String expression = null;
private List<String> checkFiles = new ArrayList<String>();
private boolean abortOnError = true;
private boolean warnIfNothingChecked = false;
private String emfAllChildrenSlot;
/**
* Sets if execution should be aborted on error.
*
* @param abortOnError
* If <code>true</code>, the execution is aborted on error,
* otherwise, the execution is continued normally.
*/
public void setAbortOnError(final boolean abortOnError) {
this.abortOnError = abortOnError;
}
/**
* Adds a check file.
*
* @param checkFile
* the check file
*/
public void addCheckFile(final String checkFile) {
this.checkFiles.add(checkFile);
}
/**
* Sets the expression to check. This property only works for non-EMF based
* models. For EMF based models, use
* <code>setEmfAllChildrenSlot(String)</code>.
*
* @param expression
* the expression to check
*/
public void setExpression(final String expression) {
this.expression = expression;
}
/**
* Sets if a warning should be issued if nothing has been checked.
*
* @param warn
* If <code>true</code>, a warning is issued in case nothing has
* been checked, otherwise no warning is issued.
*/
public void setWarnIfNothingChecked(boolean warn) {
warnIfNothingChecked = warn;
}
/**
* Sets the expression for the <code>emfAllChildren</code> property. This
* property only works for EMF based models. For all other kinds of models
* use <code>setExpression(String)</code>.
*
* @param childExpression
* the expression
*/
public void setEmfAllChildrenSlot(final String childExpression) {
emfAllChildrenSlot = childExpression;
}
/**
* @see org.eclipse.emf.mwe.workflow.lib.AbstractWorkflowComponent#getLogMessage()
*/
@Override
public String getLogMessage() {
StringBuilder b = new StringBuilder();
if (emfAllChildrenSlot != null) {
b.append("slot " + emfAllChildrenSlot + " ");
}
else {
b.append("expression " + expression + " ");
}
b.append("check file(s): ");
for (String f : checkFiles) {
b.append(f + " ");
}
return b.toString();
}
/**
* @see org.eclipse.emf.mwe.workflow.WorkflowComponent#getComponentName()
*/
@Override
public String getComponentName() {
return COMPONENT_NAME;
}
@Override
protected void invokeInternal2(final WorkflowContext ctx, final ProgressMonitor monitor, final Issues issues) {
final ExecutionContextImpl executionContext = getExecutionContext(ctx);
if (monitor != null) {
executionContext.setMonitor(monitor);
}
final Collection<?> model = getExpressionResult(executionContext, ctx, expression);
for (String checkFile : checkFiles) {
CheckFacade.checkAll(checkFile, model, executionContext, issues, warnIfNothingChecked);
}
if (abortOnError && issues.hasErrors())
throw new WorkflowInterruptedException("Errors during validation.");
}
@Override
protected void checkConfigurationInternal(final Issues issues) {
super.checkConfigurationInternal(issues);
if ((expression == null) && (emfAllChildrenSlot != null)) {
expression = emfAllChildrenSlot + ".eAllContents.union( {" + emfAllChildrenSlot + "} )";
}
else if ((expression != null) && (emfAllChildrenSlot == null)) {
// ok - do nothing, expression already has a reasonable value
}
else {
issues.addError(this, "You have to set one of the properties 'expression' and 'emfAllChildrenSlot'!");
}
if (checkFiles.isEmpty()) {
issues.addError(this, "Property 'checkFile' not set!");
}
}
@SuppressWarnings("unchecked")
private Collection<?> getExpressionResult(final ExecutionContext exeCtx, final WorkflowContext context,
final String expression2) {
final ExpressionFacade f = new ExpressionFacade(exeCtx);
final Map<String, Object> ctx = new HashMap<String, Object>();
final String[] names = context.getSlotNames();
for (int i = 0; i < names.length; i++) {
final String name = names[i];
ctx.put(name, context.get(name));
}
final Object result = f.evaluate(expression2, ctx);
if (result instanceof Collection)
return (Collection<?>) result;
else if (result == null)
return Collections.EMPTY_SET;
else
return Collections.singleton(result);
}
}