Can we define constructors for a GUI-designed Agent? - anylogic

I created a GUI-designed Agent MyBatch. I would like to know if it is possible to define a constructor for this agent.
More specifically, I would need it in fluidToAgent, where I would like the new Agent to be the type of MyBatch.
However,
New agent = new MyBatch()
gives me an 'empty' MyBatch, where I would like have something along the lines of
New agent = new MyBatch(batch.variable_1, batch.variable_2, etc...)
so that I can initialize New agent with data contained in the current batch
Thanks

The easiest way to do this is to add parameters to your GUI constructed agent. Then
new agent = new MyBatch( param1, param2...)
You can go to the agents properties window to see which order the parameters should be passed in. This get the parameters passed in and set, and then you can use OnStartUp action to perform any logic you would like.
One important item to note is that if you create an AnyLogic agent via new MyBatch().. you must also call createAndStart( anyAgent ) to initialize any objects on the canvas.
If you use a population of MyBatch, and then use
new agent = add_populationMyBatch( param1, param2, ...)
you do not have to worry about calling createAndStart
Another alternative is to have you own initialization function within MyBatch. You can create the agent via new agent = new MyBatch() and then call agent.init( variables passed in ). Within init you can call createAndStart and whatever other code you would like.

Related

Deploying an application with Application Parameters through FabricClient

I am currently deploying multiple application instances through the FabricClient. A simple implementation of this would be:
var appDesc = new ApplicationDescription(new Uri(appName), appType, appVersion);
await fabricClient.ApplicationManager.CreateApplicationAsync(appDesc);
Whenever this code is executed the new application is started with its default parameters. It is possible to add name value pairs to the ApplicationDescription through its constructor. I would prefer to use the ApplicationParameters.xml files however. Is there a way to specify the new application to use an ApplicationParameters.xml file for its parameters?
Try creating the application with the ApplicationDescription(Uri, String, String, NameValueCollection) overload.
The last parameter is the list of parameters passed to the application.

Disable logging on FileConfigurationSourceChanged - LogEnabledFilter

I want Administrators to enable/disable logging at runtime by changing the enabled property of the LogEnabledFilter in the config.
There are several threads on SO that explain workarounds, but I want it this way.
I tried to change the Logging Enabled Filter like this:
private static void FileConfigurationSourceChanged(object sender, ConfigurationSourceChangedEventArgs e)
{
var fcs = sender as FileConfigurationSource;
System.Diagnostics.Debug.WriteLine("----------- FileConfigurationSourceChanged called --------");
LoggingSettings currentLogSettings = e.ConfigurationSource.GetSection("loggingConfiguration") as LoggingSettings;
var fdtl = currentLogSettings.TraceListeners.Where(tld => tld is FormattedDatabaseTraceListenerData).FirstOrDefault();
var currentLogFileFilter = currentLogSettings.LogFilters.Where(lfd => { return lfd.Name == "Logging Enabled Filter"; }).FirstOrDefault();
var filterNewValue = (bool)currentLogFileFilter.ElementInformation.Properties["enabled"].Value;
var runtimeFilter = Logger.Writer.GetFilter<LogEnabledFilter>("Logging Enabled Filter");
runtimeFilter.Enabled = filterNewValue;
var test = Logger.Writer.IsLoggingEnabled();
}
But test reveals always the initially loaded config value, it does not change.
I thought, that when changing the value in the config the changes will be propagated automatically to the runtime configuration. But this isn't the case!
Setting it programmatically as shown in the code above, doesn't work either.
It's time to rebuild Enterprise Library or shut it down.
You are right that the code you posted does not work. That code is using a config file (FileConfigurationSource) as the method to configure Enterprise Library.
Let's dig a bit deeper and see if programmatic configuration will work.
We will use the Fluent API since it is the preferred method for programmatic configuration:
var builder = new ConfigurationSourceBuilder();
builder.ConfigureLogging()
.WithOptions
.DoNotRevertImpersonation()
.FilterEnableOrDisable("EnableOrDisable").Enable()
.LogToCategoryNamed("General")
.WithOptions.SetAsDefaultCategory()
.SendTo.FlatFile("FlatFile")
.ToFile(#"fluent.log");
var configSource = new DictionaryConfigurationSource();
builder.UpdateConfigurationWithReplace(configSource);
var defaultWriter = new LogWriterFactory(configSource).Create();
defaultWriter.Write("Test1", "General");
var filter = defaultWriter.GetFilter<LogEnabledFilter>();
filter.Enabled = false;
defaultWriter.Write("Test2", "General");
If you try this code the filter will not be updated -- so another failure.
Let's try to use the "old school" programmatic configuration by using the classes directly:
var flatFileTraceListener = new FlatFileTraceListener(
#"program.log",
"----------------------------------------",
"----------------------------------------"
);
LogEnabledFilter enabledFilter = new LogEnabledFilter("Logging Enabled Filter", true);
// Build Configuration
var config = new LoggingConfiguration();
config.AddLogSource("General", SourceLevels.All, true)
.AddTraceListener(flatFileTraceListener);
config.Filters.Add(enabledFilter);
LogWriter defaultWriter = new LogWriter(config);
defaultWriter.Write("Test1", "General");
var filter = defaultWriter.GetFilter<LogEnabledFilter>();
filter.Enabled = false;
defaultWriter.Write("Test2", "General");
Success! The second ("Test2") message was not logged.
So, what is going on here? If we instantiate the filter ourselves and add it to the configuration it works but when relying on the Enterprise Library configuration the filter value is not updated.
This leads to a hypothesis: when using Enterprise Library configuration new filter instances are being returned each time which is why changing the value has no effect on the internal instance being used by Enterprise Library.
If we dig into the Enterprise Library code we (eventually) hit on LoggingSettings class and the BuildLogWriter method. This is used to create the LogWriter. Here's where the filters are created:
var filters = this.LogFilters.Select(tfd => tfd.BuildFilter());
So this line is using the configured LogFilterData and calling the BuildFilter method to instantiate the applicable filter. In this case the BuildFilter method of the configuration class LogEnabledFilterData BuildFilter method returns an instance of the LogEnabledFilter:
return new LogEnabledFilter(this.Name, this.Enabled);
The issue with this code is that this.LogFilters.Select returns a lazy evaluated enumeration that creates LogFilters and this enumeration is passed into the LogWriter to be used for all filter manipulation. Every time the filters are referenced the enumeration is evaluated and a new Filter instance is created! This confirms the original hypothesis.
To make it explicit: every time LogWriter.Write() is called a new LogEnabledFilter is created based on the original configuration. When the filters are queried by calling GetFilter() a new LogEnabledFilter is created based on the original configuration. Any changes to the object returned by GetFilter() have no affect on the internal configuration since it's a new object instance and, anyway, internally Enterprise Library will create another new instance on the next Write() call anyway.
Firstly, this is just plain wrong but it is also inefficient to create new objects on every call to Write() which could be invoked many times..
An easy fix for this issue is to evaluate the LogFilters enumeration by calling ToList():
var filters = this.LogFilters.Select(tfd => tfd.BuildFilter()).ToList();
This evaluates the enumeration only once ensuring that only one filter instance is created. Then the GetFilter() and update filter value approach posted in the question will work.
Update:
Randy Levy provided a fix in his answer above.
Implement the fix and recompile the enterprise library.
Here is the answer from Randy Levy:
Yes, you can disable logging by setting the LogEnabledFiter. The main
way to do this would be to manually edit the configuration file --
this is the main intention of that functionality (developers guide
references administrators tweaking this setting). Other similar
approaches to setting the filter are to programmatically modify the
original file-based configuration (which is essentially a
reconfiguration of the block), or reconfigure the block
programmatically (e.g. using the fluent interface). None of the
programmatic approaches are what I would call simple – Randy Levy 39
mins ago
If you try to get the filter and disable it I don't think it has any
affect without a reconfiguration. So the following code still ends up
logging: var enabledFilter = logWriter.GetFilter();
enabledFilter.Enabled = false; logWriter.Write("TEST"); One non-EntLib
approach would just to manage the enable/disable yourself with a bool
property and a helper class. But I think the priority approach is a
pretty straight forward alternative.
Conclusion:
In your custom Logger class implement a IsLoggenabled property and change/check this one at runtime.
This won't work:
var runtimeFilter = Logger.Writer.GetFilter<LogEnabledFilter>("Logging Enabled Filter");
runtimeFilter.Enabled = false/true;

Difference between Identity link type in activiti

I am using activiti for my application.Here,when i'm assigning a task to the particular user sometimes the identity link type is as 'PARTICIPANT' and sometimes it is like 'CANDIDATE".In the modeler,for the user task i'm assigning the variable to assignee as
assignee = ${user} //In my case user = "kermit" or customUser
If the identity link type is 'participant' it has the process instance id.With the process instance id i'm getting the task as null.Is there any way to get the task.
val processEngine: ProcessEngine = ProcessEngineConfiguration.createStandaloneProcessEngineConfiguration.buildProcessEngine()
val taskService: TaskService = processEngine.getTaskService
val task = taskService.createTaskQuery().processInstanceId(idl.getProcessInstanceId).singleResult()
Can anyone please tell me how the identity link type will be generated during runtime as 'candidate' or 'participant'.
'candidate' is added when the user task has the 'candidate groups' or 'candidate users' set.
'participant' is set for a user that is the assignee, the task owner or the person who has completed the task (not necessarily the same as assignee/owner for the Activiti API).
It is also possible to add a custom user/group with these identityLink types to a task, using the taskService.addUserIdentityLink and taskService.addGroupIdentityLink method. The types are in the org.activiti.engine.task.IdentityLinkType class.

Symfony form gets messy when calling getObject() in form configuration

I have a Strain model that has a belongsTo relationship with a Sample model, i. e. a strain belongs to a sample.
I am configuring a hidden field in the StrainForm configure() method this way:
$defaultId = (int)$this->getObject()->getSample()->getTable()->getDefaultSampleId();
$this->setWidget('sample_id', new sfWidgetFormInputHidden(array('default' => $defaultId)));
Whenever I create a new Strain, the $form->save() fails. The debug toolbar revealed that it tries to save a Sample object first and I do not know why.
However, if I retrieve the default sample ID using the table it works like a charm:
$defaultId = (int)Doctrine_Core::getTable('Sample')->getDefaultSampleId();
$this->setWidget('sample_id', new sfWidgetFormInputHidden(array('default' => $defaultId)));
My question here is what can be happening with the getObject()->getSample()... sequence of methods that causes the StrainForm to think it has to save a Sample object instead of Strain.
I tried to debug with xdebug but I cannot came up with a clear conclusion.
Any thoughts?
Thanks!!
When you call getSample its creating a Sample instance. This is automatically attached to the Strain object, thus when you save you also save the Sample.
An altenrative to calling getSample would be to chain through Strain object to the Sample table since i assume youre only doing this so your not hardcodeing the Sample's name in related form:
// note Sample is the alias not necessarily the Model name
$defaultId = Doctrine_Core::getTable($this->getObject()->getTable()->getRelation('Sample')->getModel())->getDefaultId();
Your solution probably falls over because you can't use getObject() on a new form (as at that stage the object simply doesn't exist).
Edit: Why don't you pass the default Sample in via the options array and then access it from within the form class via $this->getOption('Sample') (if I remember correctly)?

UI Automation - Select object based on multiple Identifiers

I am new to this. I am using UI Automation to automate my application. Is there a way to identify element based on multiple identifier.
currently the below syntax only able to identify based on one identifier.
AutomationElement okbtn = dialogbox.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "OK"));
I would like to take identify element by both NameProperty and ControlTypeProperty.
Is this possible?
Condition cMenuItem = new AndCondition(
new PropertyCondition(AutomationElement.LocalizedControlTypeProperty,"text"),
new PropertyCondition(AutomationElement.NameProperty,"Appointment"));
AutomationElement aeMenuItem = aeTaskMenu.FindFirst(TreeScope.Descendants, cMenuItem);