How can the Repast file sink filename be set programmatically? - repast-simphony

Does anybody know if there is a simple way to make the filename element path of an file sink variable according to one field in the model?
So instead of using a fix path like :
fixed_path/filename.csv
{variable_path}/filename.csv

The attached ModelInitializer shows how to do this. I also copied the code below in case attachments doesn’t go through. To enable the ModelInitializer, you need to add the following to the scenario.xml file:
<model.initializer class="PredatorPrey.MyInitializer" />
I tested this in the Predator Prey demo so you should change the class package name. In the ModelInitializer example, you need to specify the root context ID which is the same as the context ID in the context.xml file. And you should specify the variable output folder name. This example requires a file name to be specified in the file sink as you would normally do and it inserts the variable path. On caveat is that the variable folder path will be saved in the scenario if the scenario is saved in the GUI, however this code will check for any existing path and simply replace the path with the outputFolder string. So you should put the entire path in the outputFolder string and not just part of it, or change the code behavior as needed.
package PredatorPrey;
import java.io.File;
import repast.simphony.data2.engine.FileSinkComponentControllerAction;
import repast.simphony.data2.engine.FileSinkDescriptor;
import repast.simphony.engine.controller.NullAbstractControllerAction;
import repast.simphony.engine.environment.ControllerAction;
import repast.simphony.engine.environment.RunEnvironmentBuilder;
import repast.simphony.engine.environment.RunState;
import repast.simphony.scenario.ModelInitializer;
import repast.simphony.scenario.Scenario;
import repast.simphony.util.collections.Tree;
public class MyInitializer implements ModelInitializer {
#Override
public void initialize(final Scenario scen, RunEnvironmentBuilder builder) {
scen.addMasterControllerAction(new NullAbstractControllerAction() {
String rootContextID = "Predator Prey";
String outputFolder = "testoutfolder";
#Override
public void batchInitialize(RunState runState, Object contextId) {
Tree<ControllerAction> scenarioTree = scen.getControllerRegistry().getActionTree(rootContextID);
findFileSinkTreeChildren(scenarioTree, scenarioTree.getRoot(), outputFolder);
// Reset the scenario dirty flag so the changes made to the file sink
// descriptors don't prompt a scenario save in the GUI
scen.setDirty(false);
}
});
}
public static void findFileSinkTreeChildren(Tree<ControllerAction> tree,
ControllerAction parent, String outputFolder){
// Check each ControllerAction in the scenario and if it is a FileSink,
// modify the output path to include the folder
for (ControllerAction act : tree.getChildren(parent)){
if (act instanceof FileSinkComponentControllerAction){
FileSinkDescriptor descriptor = ((FileSinkComponentControllerAction)act).getDescriptor();
String fileName = descriptor.getFileName();
// remove any prefix directories from the file name
int lastSeparatorIndex = fileName.lastIndexOf(File.separator);
// Check for backslash separator
if (fileName.lastIndexOf('\\') > lastSeparatorIndex)
lastSeparatorIndex = fileName.lastIndexOf('\\');
// Check for forward slash operator
if (fileName.lastIndexOf('/') > lastSeparatorIndex)
lastSeparatorIndex = fileName.lastIndexOf('/');
if (lastSeparatorIndex > 0){
fileName = fileName.substring(lastSeparatorIndex+1, fileName.length());
}
descriptor.setFileName(outputFolder + File.separator + fileName);
}
else findFileSinkTreeChildren(tree, act, outputFolder);
}
}
}

Related

Extent Report: Name of output file does not change even when defined

Im not able to change the name of the outputfile from the extent reports. It does always create the report file called index.html.
In my code, i want to display the name + date/time.html
Here is the codeline for the path definition:
private const string ExtentReportPath = #".\ExtentReports\";
[OneTimeSetUp]
public void ExtentStart()
{
ExtentHtmlReporter htmlreporter = new ExtentHtmlReporter(ExtentReportPath + "UnlockInstruction_Test" + DateTime.Now.ToString("yyyy_MM_dd_HH_mm_ss") + ".html");
extent = new ExtentReports();
extent.AttachReporter(htmlreporter);
}
[OneTimeTearDown]
public void ExtentClose()
{
extent.Flush();
}
First solution ive found is:
I changed ExtentHtmlReporter to ExtentV3HtmlReporter.
But after using ExtentV3HtmlReporter, VS is displaying a warning which says, that this method is obsolete and wont be supported in the future.. so still waiting for a up to date solution.
From what I read the static name (index) is expected behavior to increase the efficiency of reporting.
You can add a unique name to the folder name instead of the file, so you would create sub-folders for each index file like this:
String path =System.getProperty("user.dir")+"//reports//"+time+"//index.html";
ExtentSparkReporter reporter = new ExtentSparkReporter(path);

XDocReport converting odt to pdf how to set proper locale

I'm trying to convert some *.odt file to *.pdf using IXDocReport.
Here is the hypothetical content of the *.odt file: ${amount?string.currency} to be paid
Here is the code I do conversion with (you can run it in kotlin REPL):
import fr.opensagres.xdocreport.converter.ConverterTypeTo
import fr.opensagres.xdocreport.converter.ConverterTypeVia
import fr.opensagres.xdocreport.converter.Options
import fr.opensagres.xdocreport.document.IXDocReport
import fr.opensagres.xdocreport.document.registry.XDocReportRegistry
import fr.opensagres.xdocreport.template.TemplateEngineKind
import java.io.ByteArrayInputStream
import java.io.File
val options: Options = Options.getTo(ConverterTypeTo.PDF).via(ConverterTypeVia.ODFDOM)
val content: ByteArray = File("/home/sandro/tmp/report.odt").readBytes()
val templateId: String = "someId"
val registry: XDocReportRegistry = XDocReportRegistry.getRegistry()
val data: MutableMap<String, Any> = mutableMapOf("amount" to 10)
ByteArrayInputStream(content).use { input ->
val report: IXDocReport =
registry.loadReport(input, templateId, TemplateEngineKind.Freemarker, true)
val tmpFile: File = createTempFile("out", ".pdf")
tmpFile.outputStream().use { output ->
report.convert(data, options, output)
println(tmpFile.toString())
}
}
and the result is the pdf file with string $10.00 to be paid
How can I set needed locale to XDocReport during conversion so the result could be changed to other currencies correctly?
P.S. I cannot control the template itself - so please do not tell me to add <#setting locale="${bean.locale}"> or something else to the template itself. The only place I can change is the code. Thanks in advance.
P.P.S. I need to render many templates per request and need to set locale per each template.
I have never used XDocReport, but maybe this will work: https://github.com/opensagres/xdocreport/wiki/FreemarkerTemplate "How to configure Freemarker?"
Quotation from there:
To configure Freemarker with XDocReport you must get the Configuration instance. To do > that you must
create a class (ex :
fr.opensagres.xdocreport.MyFreemarkerConfiguration) which implements
fr.opensagres.xdocreport.document.discovery.ITemplateEngineInitializerDiscovery.
register with SPI this class by creating the file
META-INF/services/fr.opensagres.xdocreport.document.discovery.ITemplateEngineInitializerDiscovery
with the name of you class :
fr.opensagres.xdocreport.MyFreemarkerConfiguration This file should be
in your classpath (you can for instance host it in the
src/META-INF/services/ of your project).
So you will need a class like this:
public class MyFreemarkerConfiguration implements ITemplateEngineInitializerDiscovery {
[...]
public void initialize(ITemplateEngine templateEngine) {
if (TemplateEngineKind.Freemarker.name().equals( templateEngine.getKind())) {
Configuration cfg = ((FreemarkerTemplateEngine) templateEngine).getFreemarkerConfiguration();
cfg.setLocale(...);
}
}
}

Flutter: Get the filename of a File

I thought this would be pretty straight-forward, but can't seem to get this. I have a File file and it has a path file.path which spits out something like /storage/emulated/0/Android/data/my_app/files/Pictures/ca04f332.png but I can't seem to find anything to get just ca04f332.png.
You can use the basename function from the dart path library:
import 'package:path/path.dart';
File file = new File("/dir1/dir2/file.ext");
String basename = basename(file.path);
# file.ext
File file = new File("/storage/emulated/0/Android/data/my_app/files/Pictures/ca04f332.png");
String fileName = file.path.split('/').last;
print(fileName);
output = ca04f332.png
Since Dart Version 2.6 has been announced and it's available for flutter version 1.12 and higher, You can use extension methods. It will provide a more readable and global solution to this problem.
file_extensions.dart :
import 'dart:io';
extension FileExtention on FileSystemEntity{
String get name {
return this?.path?.split("/")?.last;
}
}
and name getter is added to all the file objects. You can simply just call name on any file.
main() {
File file = new File("/dev/dart/work/hello/app.dart");
print(file.name);
}
Read the document for more information.
Note:
Since extension is a new feature, it's not fully integrated into IDEs yet and it may not be recognized automatically. You have to import your extension manually wherever you need that. Just make sure the extension file is imported:
import 'package:<your_extention_path>/file_extentions.dart';
Direct way:
File file = File('/foo/bar/baz/my_image.jpg');
String fileName = file.path.split(Platform.pathSeparator).last; // my_image.jpg
Using an extension:
1. Create an extension:
extension FileEx on File {
String get name => path.split(Platform.pathSeparator).last;
}
2. Usage:
File file = File('/foo/bar/baz/my_image.jpg');
String fileName = file.name; // my_image.jpg
Easy way to get name or any other file handling operations.I recommend to use this plugin : https://pub.dev/packages/file_support
main() {
String filename= FileSupport().getFileNameWithoutExtension(<File Object>);
}
You cane use extension method No need to use any package
Create Method like this
extension FileNameExtension on File {
String getFileName() {
String fileName = path.split('/').last;
return fileName;
}
}
implement
File file = File("yourpath/example.pdf");
file.getFileName() // result => example.pdf

How to get the name of a temporary file created by File.tmpfile in D2?

I need to generate a temporary file, fill it with some data and feed it to an external program. Based on description of D available here I'm using File.tmpfile() method:
auto f = File.tmpfile();
writeln(f.name());
which doesn't provide a way to get the generated file name. It's documented that name might be empty. In Python I would do that like this:
(o_fd, o_filename) = tempfile.mkstemp('.my.own.suffix')
Is there a simple, safe and cross-platform way to do that in D2?
Due to how tmpfile() works, if you need the name of the file you can't use it. However, I have already created a module to work with temporary files. It uses conditional compilation to decide on the method of finding the temporary directory. On windows, it uses the %TMP% environment variable. On Posix, it uses /tmp/.
This code is licensed under the WTFPL, so you can do whatever you want with it.
module TemporaryFiles;
import std.conv,
std.random,
std.stdio;
version(Windows) {
import std.process;
}
private static Random rand;
/// Returns a file with the specified filename and permissions
public File getTempFile(string filename, string permissions) {
string path;
version(Windows) {
path = getenv("TMP") ~ '\\';
} else version(Posix) {
path = "/tmp/";
// path = "/var/tmp/"; // Uncomment to survive reboots
}
return File(path~filename, permissions);
}
/// Returns a file opened for writing, which the specified filename
public File getTempFile(string filename) {
return getTempFile(filename, "w");
}
/// Returns a file opened for writing, with a randomly generated filename
public File getTempFile() {
string filename = to!string(uniform(1L, 1000000000L, rand)) ~ ".tmp";
return getTempFile(filename, "w");
}
To use this, simply call getTempFile() with whatever arguments you want. Defaults to write permission.
As a note, the "randomly generated filenames" aren't truely random, as the seed is set at compile time.

How do I create a custom directive for Apache Velocity

I am using Apache's Velocity templating engine, and I would like to create a custom Directive. That is, I want to be able to write "#doMyThing()" and have it invoke some java code I wrote in order to generate the text.
I know that I can register a custom directive by adding a line
userdirective=my.package.here.MyDirectiveName
to my velocity.properties file. And I know that I can write such a class by extending the Directive class. What I don't know is how to extend the Directive class -- some sort of documentation for the author of a new Directive. For instance I'd like to know if my getType() method return "BLOCK" or "LINE" and I'd like to know what should my setLocation() method should do?
Is there any documentation out there that is better than just "Use the source, Luke"?
On the Velocity wiki, there's a presentation and sample code from a talk I gave called "Hacking Velocity". It includes an example of a custom directive.
Also was trying to come up with a custom directive. Couldn't find any documentation at all, so I looked at some user created directives: IfNullDirective (nice and easy one), MergeDirective as well as velocity build-in directives.
Here is my simple block directive that returns compressed content (complete project with some directive installation instructions is located here):
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import org.apache.velocity.context.InternalContextAdapter;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.exception.TemplateInitException;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.runtime.directive.Directive;
import org.apache.velocity.runtime.parser.node.Node;
import org.apache.velocity.runtime.log.Log;
import com.googlecode.htmlcompressor.compressor.HtmlCompressor;
/**
* Velocity directive that compresses an HTML content within #compressHtml ... #end block.
*/
public class HtmlCompressorDirective extends Directive {
private static final HtmlCompressor htmlCompressor = new HtmlCompressor();
private Log log;
public String getName() {
return "compressHtml";
}
public int getType() {
return BLOCK;
}
#Override
public void init(RuntimeServices rs, InternalContextAdapter context, Node node) throws TemplateInitException {
super.init(rs, context, node);
log = rs.getLog();
//set compressor properties
htmlCompressor.setEnabled(rs.getBoolean("userdirective.compressHtml.enabled", true));
htmlCompressor.setRemoveComments(rs.getBoolean("userdirective.compressHtml.removeComments", true));
}
public boolean render(InternalContextAdapter context, Writer writer, Node node)
throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException {
//render content to a variable
StringWriter content = new StringWriter();
node.jjtGetChild(0).render(context, content);
//compress
try {
writer.write(htmlCompressor.compress(content.toString()));
} catch (Exception e) {
writer.write(content.toString());
String msg = "Failed to compress content: "+content.toString();
log.error(msg, e);
throw new RuntimeException(msg, e);
}
return true;
}
}
Block directives always accept a body and must end with #end when used in a template. e.g. #foreach( $i in $foo ) this has a body! #end
Line directives do not have a body or an #end. e.g. #parse( 'foo.vtl' )
You don't need to both with setLocation() at all. The parser uses that.
Any other specifics i can help with?
Also, have you considered using a "tool" approach? Even if you don't use VelocityTools to automatically make your tool available and whatnot, you can just create a tool class that does what you want, put it in the context and either have a method you call to generate content or else just have its toString() method generate the content. e.g. $tool.doMyThing() or just $myThing
Directives are best for when you need to mess with Velocity internals (access to InternalContextAdapter or actual Nodes).
Prior to velocity v1.6 I had a #blockset($v)#end directive to be able to deal with a multiline #set($v) but this function is now handled by the #define directive.
Custom block directives are a pain with modern IDEs because they don't parse the structure correctly, assuming your #end associated with #userBlockDirective is an extra and paints the whole file RED. They should be avoided if possible.
I copied something similar from the velocity source code and created a "blockset" (multiline) directive.
import org.apache.velocity.runtime.directive.Directive;
import org.apache.velocity.runtime.RuntimeServices;
import org.apache.velocity.runtime.parser.node.Node;
import org.apache.velocity.context.InternalContextAdapter;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.TemplateInitException;
import java.io.Writer;
import java.io.IOException;
import java.io.StringWriter;
public class BlockSetDirective extends Directive {
private String blockKey;
/**
* Return name of this directive.
*/
public String getName() {
return "blockset";
}
/**
* Return type of this directive.
*/
public int getType() {
return BLOCK;
}
/**
* simple init - get the blockKey
*/
public void init( RuntimeServices rs, InternalContextAdapter context,
Node node )
throws TemplateInitException {
super.init( rs, context, node );
/*
* first token is the name of the block. I don't even check the format,
* just assume it looks like this: $block_name. Should check if it has
* a '$' or not like macros.
*/
blockKey = node.jjtGetChild( 0 ).getFirstToken().image.substring( 1 );
}
/**
* Renders node to internal string writer and stores in the context at the
* specified context variable
*/
public boolean render( InternalContextAdapter context, Writer writer,
Node node )
throws IOException, MethodInvocationException,
ResourceNotFoundException, ParseErrorException {
StringWriter sw = new StringWriter(256);
boolean b = node.jjtGetChild( 1 ).render( context, sw );
context.put( blockKey, sw.toString() );
return b;
}
}