/**
* Copyright 2004-2016 Riccardo Solmi. All rights reserved.
* This file is part of the Whole Platform.
*
* The Whole Platform is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Whole Platform is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>.
*/
package org.whole.lang.workflows.visitors;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import org.whole.lang.bindings.BindingManagerFactory;
import org.whole.lang.bindings.IBindingManager;
import org.whole.lang.iterators.IEntityIterator;
import org.whole.lang.iterators.IteratorFactory;
import org.whole.lang.java.util.JavaReflectUtils;
import org.whole.lang.model.IEntity;
import org.whole.lang.model.adapters.IEntityAdapter;
import org.whole.lang.reflect.ReflectionFactory;
import org.whole.lang.util.DataTypeUtils;
import org.whole.lang.visitors.MissingVariableException;
import org.whole.lang.workflows.model.BooleanLiteral;
import org.whole.lang.workflows.model.CreateJavaClassInstance;
import org.whole.lang.workflows.model.Expressions;
import org.whole.lang.workflows.model.IWorkflowsEntity;
import org.whole.lang.workflows.model.IntLiteral;
import org.whole.lang.workflows.model.InvokeJavaClassMethod;
import org.whole.lang.workflows.model.InvokeJavaInstanceMethod;
import org.whole.lang.workflows.model.StringLiteral;
import org.whole.lang.workflows.model.Variable;
/**
* @author Riccardo Solmi
*/
public class WorkflowsDynamicCompilerVisitor extends WorkflowsIdentityDefaultVisitor {
@Override
public boolean visitAdapter(IEntityAdapter entity) {
stagedVisit(entity.wGetAdaptee(false), 0);
return false;
}
@Override
public void visit(IWorkflowsEntity entity) {
stagedDefaultVisit(entity, 0);
}
//FIXME add compilation of Assignments before fixing
// @Override
// public void visit(CreateEntity entity) {
// final Variable resultVariable = entity.getModel();
//
// entity.getEntityName().accept(this);
// final String typeName = getResult().wStringValue();
//
// IEntityRegistryProvider provider = null;
// switch (entity.getRegistry().getValue().getOrdinal()) {
// case RegistryEnum.DEFAULT_ord:
// provider = RegistryConfigurations.DEFAULT;
// break;
// case RegistryEnum.RESOLVER_ord:
// provider = RegistryConfigurations.RESOLVER;
// break;
// case RegistryEnum.ADAPTER_ord:
// provider = RegistryConfigurations.ADAPTER;
// break;
// case RegistryEnum.STRICT_ord:
// provider = RegistryConfigurations.STRICT;
// break;
// case RegistryEnum.CUSTOM_ord:
// provider = RegistryConfigurations.CUSTOM;
// break;
// }
// final IEntityFactory ef = GenericEntityFactory.instance(provider);
//
// final Arguments arguments = entity.getArguments();
// int size = arguments.wSize();
// IEntityIterator<?>[] runnableIterators = new IEntityIterator<?>[size];
//
// if (Matcher.matchImpl(WorkflowsEntityDescriptorEnum.Assignments, arguments)) {
// for (int i=0; i<size; i++) {
// Assign argument = ((Assignments) arguments).get(i);
// String name = argument.getName().getValue();
// argument.getExpression().accept(this);
// runnableIterators[i] = getResultIterator();//FIXME
// }
// } else if (Matcher.matchImpl(WorkflowsEntityDescriptorEnum.Expressions, arguments)) {
// for (int i=0; i<size; i++) {
// ((Expressions) arguments).get(i).accept(this);
// runnableIterators[i] = getResultIterator();
// }
// }
//
// setResultIterator(IteratorFactory.multiValuedRunnableIterator(new AbstractWorkflowsRunnable() {
// public void run(IEntity selfEntity, IBindingManager bm, IEntity... argsEntities) {
// EntityDescriptor<?> ed = CommonsDataTypePersistenceParser.parseEntityDescriptor(typeName);
// if (ed == null)
// throw new IllegalArgumentException("The requested entity does not exist: "+typeName);
//
// IEntity resultValue;
// if (Matcher.matchImpl(WorkflowsEntityDescriptorEnum.Assignments, arguments)) {
// ResettableScope resettableScope = BindingManagerFactory.instance.createResettableScope();
// bm.wEnterScope(resettableScope);
//
// //FIXME
// for (int i = 0; i < arguments.wSize(); i++) {
// String name = ((Assignments) arguments).get(i).getName().getValue();
// bm.wSet(name, EntityUtils.convert(bm.wGet(name), ed.getEntityDescriptor(i)));
// }
// resultValue = ef.create(ed, bm);
//
// resettableScope.reset();
// bm.wExitScope();
// } else if (Matcher.matchImpl(WorkflowsEntityDescriptorEnum.Expressions, arguments)) {
// if (ed.getEntityKind().isData())
// resultValue = DataTypeUtils.convert(argsEntities[0], ed);
// else {
// IEntity[] values = new IEntity[argsEntities.length];
// for (int i = 0; i < values.length; i++)
// values[i] = EntityUtils.convert(argsEntities[i], ed.getEntityDescriptor(i));
// resultValue = ef.create(ed, values);
// }
// } else
// resultValue = ef.create(ed);
//
// setResult(bm, resultVariable, resultValue);
// }
// }, runnableIterators).withDomainEntity(entity));
// }
@Override
public void visit(CreateJavaClassInstance entity) {
final Variable resultVariable = entity.getResult();
Expressions arguments = entity.getArguments();
int size= arguments.wSize();
IEntityIterator<?>[] runnableIterators = new IEntityIterator<?>[2+size];
entity.getClassName().accept(this);
runnableIterators[0] = getResultIterator();
entity.getConstructor().accept(this);
runnableIterators[1] = getResultIterator();
for (int i=0; i<size; i++) {
arguments.get(i).accept(this);
runnableIterators[2+i] = getResultIterator();
}
setResultIterator(IteratorFactory.singleValuedRunnableIterator(new AbstractWorkflowsRunnable() {
public void run(IEntity selfEntity, IBindingManager bm, IEntity... argsEntities) {
String className = argsEntities[0].wStringValue();
IEntity constructorData = argsEntities[1];
Constructor<?> constructor;
if (DataTypeUtils.getDataKind(constructorData).isString())
constructor = JavaReflectUtils.getConstructor(
className, constructorData.wStringValue(), ReflectionFactory.getClassLoader(bm));
else
constructor = (Constructor<?>) constructorData.wGetValue();
Object[] arguments = toArguments(constructor.getParameterTypes(), constructor.isVarArgs(), argsEntities);
Object resultValue = JavaReflectUtils.invokeConstructor(constructor, arguments);
setResult(bm, resultVariable, resultValue, constructor.getDeclaringClass());
}
}, runnableIterators).withSourceEntity(entity));
}
@Override
public void visit(InvokeJavaClassMethod entity) {
final Variable resultVariable = entity.getResult();
Expressions arguments = entity.getArguments();
int size= arguments.wSize();
IEntityIterator<?>[] runnableIterators = new IEntityIterator<?>[2+size];
entity.getClassName().accept(this);
runnableIterators[0] = getResultIterator();
entity.getMethod().accept(this);
runnableIterators[1] = getResultIterator();
for (int i=0; i<size; i++) {
arguments.get(i).accept(this);
runnableIterators[2+i] = getResultIterator();
}
setResultIterator(IteratorFactory.multiValuedRunnableIterator(new AbstractWorkflowsRunnable() {
public void run(IEntity selfEntity, IBindingManager bm, IEntity... argsEntities) {
String className = argsEntities[0].wStringValue();
IEntity methodData = argsEntities[1];
Method method;
if (DataTypeUtils.getDataKind(methodData).isString())
method = JavaReflectUtils.getMethod(
className, methodData.wStringValue(), ReflectionFactory.getClassLoader(bm));
else
method = (Method) methodData.wGetValue();
Object[] arguments = toArguments(method.getParameterTypes(), method.isVarArgs(), argsEntities);
Object resultValue = JavaReflectUtils.invokeMethod(null, method, arguments);
setResult(bm, resultVariable, resultValue, method.getReturnType());
}
}, runnableIterators).withSourceEntity(entity));
}
@Override
public void visit(InvokeJavaInstanceMethod entity) {
final Variable resultVariable = entity.getResult();
final Variable instanceVariable = entity.getObject();
Expressions arguments = entity.getArguments();
int size= arguments.wSize();
IEntityIterator<?>[] runnableIterators = new IEntityIterator<?>[2+size];
entity.getClassName().accept(this);
runnableIterators[0] = getResultIterator();
entity.getMethod().accept(this);
runnableIterators[1] = getResultIterator();
for (int i=0; i<size; i++) {
arguments.get(i).accept(this);
runnableIterators[2+i] = getResultIterator();
}
setResultIterator(IteratorFactory.multiValuedRunnableIterator(new AbstractWorkflowsRunnable() {
public void run(IEntity selfEntity, IBindingManager bm, IEntity... argsEntities) {
String className = argsEntities[0].wStringValue();
IEntity methodData = argsEntities[1];
Method method;
if (DataTypeUtils.getDataKind(methodData).isString())
method = JavaReflectUtils.getMethod(
className, methodData.wStringValue(), ReflectionFactory.getClassLoader(bm));
else
method = (Method) methodData.wGetValue();
IEntity instanceEntity = bm.wGet(instanceVariable.getValue());
if (instanceEntity == null)
throw new MissingVariableException(instanceVariable.getValue()).withSourceEntity(getSourceEntity()).withBindings(getBindings());
Object instance = DataTypeUtils.unbox(instanceEntity, method.getDeclaringClass(), false);
Object[] arguments = toArguments(method.getParameterTypes(), method.isVarArgs(), argsEntities);
Object resultValue = JavaReflectUtils.invokeMethod(instance, method, arguments);
setResult(bm, resultVariable, resultValue, method.getReturnType());
}
}, runnableIterators).withSourceEntity(entity));
}
@Override
public void visit(Variable entity) {
String varName = entity.getValue();
setResultIterator((varName.equals("self") ?
IteratorFactory.selfIterator() : IteratorFactory.variableIterator(varName)).withSourceEntity(entity));
}
@Override
public void visit(BooleanLiteral entity) {
setResultIterator(IteratorFactory.constantIterator(
BindingManagerFactory.instance.createValue(entity.isValue()), true).withSourceEntity(entity));
}
@Override
public void visit(IntLiteral entity) {
setResultIterator(IteratorFactory.constantIterator(
BindingManagerFactory.instance.createValue(entity.getValue()), true).withSourceEntity(entity));
}
@Override
public void visit(StringLiteral entity) {
setResultIterator(IteratorFactory.constantIterator(
BindingManagerFactory.instance.createValue(entity.getValue()), true).withSourceEntity(entity));
}
}