jadex.bridge.component.impl.ArgumentsResultsComponentFeature Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jadex-platform-bridge Show documentation
Show all versions of jadex-platform-bridge Show documentation
Jadex bridge is a base package for kernels and platforms, i.e., it is used by both and provides commonly used interfaces and classes for active components and their management.
package jadex.bridge.component.impl;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import jadex.base.IPlatformConfiguration;
import jadex.base.Starter;
import jadex.bridge.IComponentIdentifier;
import jadex.bridge.IComponentStep;
import jadex.bridge.IInternalAccess;
import jadex.bridge.component.ComponentCreationInfo;
import jadex.bridge.component.IArgumentsResultsFeature;
import jadex.bridge.component.IExecutionFeature;
import jadex.bridge.modelinfo.ConfigurationInfo;
import jadex.bridge.modelinfo.IArgument;
import jadex.bridge.modelinfo.UnparsedExpression;
import jadex.commons.IValueFetcher;
import jadex.commons.SReflect;
import jadex.commons.Tuple2;
import jadex.commons.collection.wrappers.MapWrapper;
import jadex.commons.future.Future;
import jadex.commons.future.IFuture;
import jadex.commons.future.ISubscriptionIntermediateFuture;
import jadex.commons.future.SubscriptionIntermediateFuture;
import jadex.commons.future.TerminationCommand;
import jadex.javaparser.IMapAccess;
import jadex.javaparser.SJavaParser;
/**
* This feature provides arguments.
*/
public class ArgumentsResultsComponentFeature extends AbstractComponentFeature implements IArgumentsResultsFeature, IValueFetcher, IInternalArgumentsResultsFeature, IMapAccess
{
//-------- attributes --------
/** The arguments. */
protected Map arguments;
/** The results. */
protected Map results;
/** The result subscription, if any. */
protected Set>> resfuts;
/** Flag to remember when an exception was notified to a listener. */
protected boolean notified;
//-------- constructors --------
/**
* Create the feature.
*/
public ArgumentsResultsComponentFeature(IInternalAccess component, ComponentCreationInfo cinfo)
{
super(component, cinfo);
}
/**
* Initialize the feature.
*/
public IFuture init()
{
// System.out.println("cl: "+getComponent().getClassLoader());
// if(getComponent().getId().getName().toLowerCase().indexOf("intravma")!=-1)
// System.out.println("here");
// Init the arguments with parameters.
if(cinfo.getArguments()!=null)
{
for(Iterator> it=cinfo.getArguments().entrySet().iterator(); it.hasNext(); )
{
Map.Entry entry = it.next();
if(arguments==null)
this.arguments = new LinkedHashMap();
arguments.put(entry.getKey(), entry.getValue());
}
}
// Get the reverse name ([email protected] -> app1.agent1.)
IComponentIdentifier cid = getComponent().getId();
String dotname = cid.getDotName();
int idx = dotname.lastIndexOf(".");
if(idx!=-1)
{
dotname = dotname.substring(0, idx);
dotname = getReverseName(dotname);
}
@SuppressWarnings("unchecked")
Map platformargs = (Map)Starter.getPlatformValue(getComponent().getId().getRoot(), IPlatformConfiguration.PLATFORMARGS);
if(platformargs!=null)
{
IArgument[] margs = component.getModel().getArguments();
for(int i=0; i();
String argname = margs[i].getName();
// if(dotname.toLowerCase().indexOf("cli")!=-1)
// System.out.println("sdfhjsdf");
// Test different versions of argument names (highest prio first), e.g. "arg" for agent [email protected]_123
// 1) full application agent name (i.e. excluding platform), e.g. "b.a.arg"
if(platformargs.containsKey(dotname+"."+argname))
{
arguments.put(argname, platformargs.get(dotname+"."+argname));
}
// 2a) local agent name dot arg, e.g. "a.arg"
else if(platformargs.containsKey(cid.getLocalName()+"."+argname))
{
arguments.put(argname, platformargs.get(cid.getLocalName()+"."+argname));
}
// 2b) local agent name + arg, e.g. "aarg"
else if(platformargs.containsKey(cid.getLocalName()+argname))
{
arguments.put(argname, platformargs.get(cid.getLocalName()+argname));
}
// 3) agent type name
else if(platformargs.containsKey(getComponent().getModel().getName()+"."+argname))
{
arguments.put(argname, platformargs.get(getComponent().getModel().getName()+"."+argname));
}
// // todo: 4) agent type hierarchy name
// else if(platformargs.containsKey(getComponent().getModel().getName()))
// {
//
// }
// 999...) name directly contained
else if(platformargs.containsKey(argname))
{
arguments.put(argname, platformargs.get(argname));
}
}
}
}
initDefaultArguments();
// Hack?! add component identifier to result as long as we don't have better future type for results
// could one somehow use the CallLocal for that purpose instead?
this.results = new MapWrapper(new LinkedHashMap())
{
protected void entryAdded(String key, Object value)
{
postEvent(key, value);
}
protected void entryRemoved(String key, Object value)
{
postEvent(key, null);
}
protected void entryChanged(String key, Object oldvalue, Object newvalue)
{
postEvent(key, newvalue);
}
};
results.put(IComponentIdentifier.RESULTCID, getComponent().getId());
initDefaultResults();
return IFuture.DONE;
}
/**
* Get the reverse name of a dot name (component id).
* @return The reverse name as string.
*/
public static String getReverseName(String dotname)
{
List res = new ArrayList();
StringTokenizer stok = new StringTokenizer(dotname, "@,");
while(stok.hasMoreTokens())
{
res.add(0, stok.nextToken());
}
StringBuilder b = new StringBuilder();
for(int i=0; i();
arguments.put(upes[i].getName(), SJavaParser.getParsedValue(upes[i], component.getModel().getAllImports(), component.getFetcher(), component.getClassLoader()));
}
}
}
IArgument[] margs = component.getModel().getArguments();
for(int i=0; i();
// Class> argclass = margs[i].getClazz().getType(getComponent().getClassLoader());
if(margs[i].getDefaultValue().getValue()!=null && !arguments.containsKey(margs[i].getName()))
{
arguments.put(margs[i].getName(), SJavaParser.getParsedValue(margs[i].getDefaultValue(), component.getModel().getAllImports(), component.getFetcher(), component.getClassLoader()));
}
// Don't set basic type default values here, as they would overwrite java field initializer values.
// Done lazy in get() instead.
// else if(SReflect.isBasicType(argclass))
// {
// arguments.put(margs[i].getName(), SReflect.getDefaultValue(argclass));
// }
}
}
}
/**
* Init unset results from default values.
*/
protected void initDefaultResults()
{
// Init the results with initial or default values.
ConfigurationInfo ci = component.getConfiguration()!=null ? component.getModel().getConfiguration(component.getConfiguration()) : null;
if(ci!=null)
{
UnparsedExpression[] upes = ci.getResults();
for(int i=0; i shutdown()
{
doCleanup();
return IFuture.DONE;
}
/**
* Kill is only invoked, when shutdown of some (e.g. other) feature does not return due to timeout.
* The feature should do any kind of possible cleanup, but no asynchronous operations.
*/
public void kill()
{
doCleanup();
}
/**
* Perform cleanup in shutdown or kill.
*/
protected void doCleanup()
{
if(resfuts!=null)
{
Exception ex = getComponent().getException();
if(ex!=null)
{
notified = true;
for(SubscriptionIntermediateFuture> fut: resfuts)
{
fut.setExceptionIfUndone(ex);
}
}
else
{
// System.out.println("setFinished "+getComponent().getId());
for(SubscriptionIntermediateFuture> fut: resfuts)
{
fut.setFinishedIfUndone();
}
}
resfuts = null;
}
}
//-------- IValueFetcher interface --------
/**
* The feature can inject parameters for expression evaluation
* by providing an optional value fetcher. The fetch order is the reverse
* init order, i.e., later features can override values from earlier features.
*/
public IValueFetcher getValueFetcher()
{
return this;
}
/**
* Fetch the arguments.
*/
public Object fetchValue(String name)
{
Object ret;
if("$args".equals(name) || "$arguments".equals(name))
{
ret = this; // Use map access interface to provide default values for unset basic type args.
}
else
{
throw new RuntimeException("Value not found: "+name);
}
return ret;
}
//-------- IMapAccess --------
/**
* Provide default values for basic types, if not set.
*/
public Object get(Object key)
{
Object ret = null;
if(arguments!=null && arguments.containsKey(key))
{
ret = arguments.get(key);
}
else if(key instanceof String)
{
IArgument arg = getComponent().getModel().getArgument((String)key);
if(arg!=null)
{
Class> argclass = arg.getClazz().getType(getComponent().getClassLoader());
if(SReflect.isBasicType(argclass))
{
ret = SReflect.getDefaultValue(argclass);
}
}
}
return ret;
}
//-------- IArgumentsFeature interface --------
/**
* Get the arguments.
* @return The arguments.
*/
public Map getArguments()
{
return arguments==null? Collections.emptyMap(): arguments;
}
/**
* Get the current results.
* @return The current result values (if any).
*/
public Map getResults()
{
return results;
}
/**
* Get the arguments.
* @return The arguments.
*/
public IFuture