Using an Arraylist in ILOG/ODM to loop through a set of records - rule-engine

I have a requirement to loop through a set of records and compare the start date in each record with current date and output a message in the Action part of the rule. I am trying to find out if I can use an arraylist in ILOG/ODM rule XOM and use it in the rule to loop through the set of records.
Can you please suggest me the best way to implement this requirement.

Yes, you can use an arraylist in rule XOM, and iterate over it in the rule. Let's assume your rule project takes an instance of your XOM class as an input parameter with the verbalization 'test'. You would have something like below.
XOM:
import java.util.Calendar;
import java.util.Date;
import java.util.List;
public class Test
{
private List<Record> recordList;
public Test()
{
}
public void setRecordList(List<Record> recordList)
{
this.recordList = recordList;
}
public List<Record> getRecordList()
{
return recordList;
}
public static int compareWithCurrentDate( Date date)
{
Calendar cal = Calendar.getInstance();
cal.setTime( date);
return cal.compareTo( Calendar.getInstance());
}
}
import java.util.Date;
public class Record
{
private Date startDate;
public Record()
{
}
public void setStartDate(Date startDate)
{
this.startDate = startDate;
}
public Date getStartDate()
{
return startDate;
}
}
BOM Verbalization:
# Record
Record#concept.label = record
Record.startDate#phrase.action = set the start date of {this} to {start date}
Record.startDate#phrase.navigation = {start date} of {this}
# Test
Test#concept.label = test
Test.compareWithCurrentDate(java.util.Date)#phrase.navigation = compare {0} with current date
Test.recordList#phrase.action = set the record list of {this} to {record list}
Test.recordList#phrase.navigation = {record list} of {this}
Rule:
definitions
set 'current record' to a record in the record lists of test ;
if
compare the start date of 'current record' with current date is not 0
then
print "" ;

You can follow the instructions in the ODM Blogs on developerWorks under "iterating over input parameters" topic.
It can be found here:
Iterating over Input Parameters
Basically you are going to a virtual method for your ArrayList to retrieve an entry at particular loop index. The virtual method will cast the entry before returning it, but from there you should be able to perform any rule on that object.
Note that you cannot use ArrayList as an input parameter for Dynamic XOM but you can use Arrays for input parameter with a Java XOM.

Related

Comparing LocalDate with date part of LocalDateTime in apache ignite

I have a certain records in ignite cache and I want to retrieve all records for current day. For this I need to compare LocalDateTime type field of cached object with Localdate object i.e LocalDate.now(). How do I write a query to do this. In oracle TODATE(date, format) does the same thing but this function is not present in H2.
cached field datetime: 2016-08-30T05:31
date instance : 2016-08-30
SQL will be like
String sql = "select * from cacheName where date='convert(datetime) to date'";
Is it possible in H2 ?
You can use custom SQL functions for this: https://ignite.apache.org/releases/mobile/org/apache/ignite/cache/query/annotations/QuerySqlFunction.html
For example, if your value class looks like this:
public class MyValue {
#QuerySqlField
private LocalDateTime time;
public MyValue(LocalDateTime time) {
this.time = time;
}
}
You can create a function like this:
public static class MyFunctions {
#QuerySqlFunction
public static String toDate(LocalDateTime time) {
return time.format(DateTimeFormatter.ISO_LOCAL_DATE);
}
}
And provide it in the configuration like this:
cacheCfg.setSqlFunctionClasses(MyFunctions.class);
The query will look like this:
select * from MyValue where toDate(time) = '2016-08-30'

Why can't nlog read the current date

I'm using Nlog to write some logging to a textfile. Partial nlog.config:
<target name="file" xsi:type="File" fileName="${basedir}/MBWRunner_log.txt"
layout="${date} (${level}): ${message}
Exception: ${exception:format=Method, ToString}"/>
Lines in the logfile look like this:
0001-01-01 00:00:00 (Trace): MBWRunner started
As you can see the date and time are all 0. I have tested {longdate} and {date:format=yyyyMMddHHmmss} with the same result.
The application is a console app, run from an elevated commandline.
Any clues?
[EDIT] I have tested this on 2 machine's within the organisation with the same result. Please help!
Code used:
static Logger _logger = LogManager.GetCurrentClassLogger();
public static void Log(string message, LogLevel priority)
{
LogEventInfo eventinfo = new LogEventInfo(); ;
eventinfo.Message = message;
eventinfo.Level = priority;
Log(eventinfo);
}
static void Log(LogEventInfo logentry)
{
_logger.Log(logentry);
}
UPDATE:
#edosoft I think the problem is your use of the default constructor for LogEventInfo. If you look at the source for LogEventInfo here
https://github.com/NLog/NLog/blob/master/src/NLog/LogEventInfo.cs
You will see that using the default constructor does not populate the .TimeStamp field, so the field will probably just default to the default value for DateTime, which I assume is DateTime.MinValue. You should use one of the other constructors or one of the Create methods. Since you are setting only the Message and Level fields, I would suggest either:
var logEvent = new LogEventInfo(priority, "", message); //Second param is logger name.
Or
var logEvent = LogEventInfo.Create(priority, "", message);
From the NLog source for DateLayoutRenderer (from here) we can see that the date value that gets written as part of the logging stream is calculated like this:
protected override void Append(StringBuilder builder, LogEventInfo logEvent)
{
var ts = logEvent.TimeStamp;
if (this.UniversalTime)
{
ts = ts.ToUniversalTime();
}
builder.Append(ts.ToString(this.Format, this.Culture));
}
What is happening here is that the DateLayoutRenderer is getting the TimeStamp value from the LogEventInfo object (NLog creates one of these each time you use the Logger.Trace, Logger.Debug, Logger.Info, etc methods. You can also create LogEventInfo objects yourself and log them with the Logger.Log method).
By default, when a LogEventInfo object is created, its TimeStamp field is set like this (from the source for LogEventInfo here) (note the use of CurrentTimeGetter.Now):
public LogEventInfo(LogLevel level, string loggerName, IFormatProvider formatProvider, [Localizable(false)] string message, object[] parameters, Exception exception)
{
this.TimeStamp = CurrentTimeGetter.Now;
this.Level = level;
this.LoggerName = loggerName;
this.Message = message;
this.Parameters = parameters;
this.FormatProvider = formatProvider;
this.Exception = exception;
this.SequenceID = Interlocked.Increment(ref globalSequenceId);
if (NeedToPreformatMessage(parameters))
{
this.CalcFormattedMessage();
}
}
The TimeStamp field is set in the LogEventInfo constructor using the TimeSource.Current.Now property, whose implementation can be seen here.
(UPDATE - At some point NLog changed from using CurrentTimeGetter to a more generic approach of having a TimeSource object that has several flavors (one of which, CachedTimeSource, is essentially the same as CurrentTimeGetter)).
To save the trouble of navigating the link, here is the source for CachedTimeSource:
public abstract class CachedTimeSource : TimeSource
{
private int lastTicks = -1;
private DateTime lastTime = DateTime.MinValue;
/// <summary>
/// Gets raw uncached time from derived time source.
/// </summary>
protected abstract DateTime FreshTime { get; }
/// <summary>
/// Gets current time cached for one system tick (15.6 milliseconds).
/// </summary>
public override DateTime Time
{
get
{
int tickCount = Environment.TickCount;
if (tickCount == lastTicks)
return lastTime;
else
{
DateTime time = FreshTime;
lastTicks = tickCount;
lastTime = time;
return time;
}
}
}
}
The purpose of this class is to use a relatively cheap operation (Environment.Ticks) to limit access to a relatively expensive operation (DateTime.Now). If the value of Ticks does not change from call to call (from one logged message to the next), then the value of DateTime.Now retrieved the this time will be the same as the value of DateTime.Now retrieved this time, so just use the last retrieved value.
With all of this code in play (and with Date/Time logging apparently working for most other people), one possible explanation of your problem is that you are using the Logger.Log method to log your messages and you are building the LogEventInfo objects yourself. By default, if you just new a LogEventInfo object, the automatic setting of the TimeStamp property should work fine. It is only dependent on Environment.Ticks, DateTime.Now, and the logic that reuses the last DateTime.Now value, if appropriate.
Is it possible that you are creating a LogEventInfo object and then setting its TimeStamp property to DateTime.MinValue? I ask because the date that is being logged is DateTime.MinValue.
The only other explanation that I can think of would be if Environment.Ticks returns -1 for some reason. If it did, then CurrentTimeGetter would always return the initial value of the lastDateTime private member variable. I can't imagine a scenario where Environment.Ticks would return -1.

How to bind multiple form elements to a single variable with the Play! framework

I am using the Play! framework, version 1. I have a form with 3 different select elements for day, month and year. I want to bind these to the birth date of a user (public Date birthDate defined in class User). How can I do this? Thanks.
You can create three setters getters in your class for day, month and year and update your date with these values. The best way to do that is to use joda date classes
public class MyClass {
public DateMidnight birthDate;
public int getBirthDateYear() {
return birthDate.getYear();
}
public void setBirthDateYear(int year) {
birthDate = birthDate.withYear(year);
}
}
and same thing with "monthOfYear" and "dayOfMonth"
I don't think it's worth fussing about with anything in the model, play can do this all in the controller, it's a bit of logic but should be no big deal in a smaller app. Assuming your select boxes POST numbers in your controller and you send other user stuff that mapped properly by name to user properties:
public static void save(User user, String day, String month, String year) {
DateFormat formatter = new SimpleDateFormat("MMddyy");
Date birthDate = formatter.parse(month + day + year);
user.birthDate = birthDate;
user.save();
}

Playframework How to transform query.ResultList to VO

The version of Playframework is 1.2.x,and I want to transform the query.ResultList to VO.
I created a Part entity bean as below:
#Entity
#Table(name="evaluation_part")
public class Part extends Model {
public String name;
public String collegeName;
public int peopleNum;
}
The data:
id name collegeName peopleNum
1 Jsj1 JJJJ 32
2 Jsj2 JJJJ 23
3 Jsj3 JJJJ 32
4 Tjb1 TTTT 11
5 Tjb2 TTTT 14
6 Tjb3 TTTT 16
My value object class:
public class PartVO {
public String collegeName;
public int peopleNum;
}
And I want to use the native query to get the result:
String sql="select collegeName,SUM(peopleNum) as peopleNum from evaluation_part group by collegeName";
The query result is:
collegeName peopleNum
TTTT 41
JJJJ 87
I tried:
String sql="select collegeName,SUM(peopleNum) as peopleNum from evaluation_part group by collegeName";
Query query =JPA.em().createNativeQuery(sql);
List<PartVO> partVOs = query.getResultList();
for(int i=0;i<partVOs.size();i++) {
System.out.println(partVOs.get(i).collegeName);
}
Following error is what i am getting
ClassCastException occured : [Ljava.lang.Object; cannot be cast to valueobject.PartVO
You don't have to user raw sql to do that. With hql you can use the new operator to create your VO (see http://docs.jboss.org/hibernate/orm/3.3/reference/en/html/queryhql.html#queryhql-select)
You have to define a two arg constructor in your partVO class, then you can do
select new package.PartVO(collegeName, SUM(peopleNum)) from Part group by collegeName
Solution 1:Only use 'select new Part()'(constructor defined in the Part class) in the HQL that u can convert object to Part.Hibernate use reflection to automatically inject all the fields u need.
Solution 2:Here the returned type of result must be Object[],so that u can got every field of the record fetched from database by the index of array;
The difference between solution1 and solution2:the previous use constructor in the query and the later transform a record into Object[].
In your case,ignore the complex relationship between entities,solutions above will make work.
Referenced Code here:
package controllers;
import play.*;
import play.db.jpa.JPA;
import play.mvc.*;
import java.util.*;
import models.*;
/**
* This demo is intended for fetching data from MYSQL.
* #author dhl#oopsplay.org
*/
public class Application extends Controller {
public static void index() {
render();
}
/**
* Prepare some data to test.
*/
public static void addPart() {
//Add a part record to database.
Part newPart=new Part("software","zjut",8).save();
if(newPart.isPersistent()){
renderText("Add successfully,there are %s records in the \'evaluation_part\' table.For convenience,please click the back button in the browser to go back previous page.",Part.count());
}
}
/**
* Fetch part entities from database;
*/
public static void fetchPart() {
//-------------------Solution 1-------------------
//[Pay attention]:Only use 'select new Part()'(constructor defined in the Part class) in the query that u can convert object to Part.
//Hibernate use reflection to automatically inject all the fields u need.
List<Part> parts1=JPA.em().createQuery("select new Part(name,collegeName,peopleNum) from Part").getResultList();
//For convenience, i output the detail in the console, focus on the change there.
Logger.info("The name of first record is :%s", parts1.get(0).name);
//-------------------Solution 2-------------------
//[Pay attention]:Here the returned type of result must be Object[],so that u can got every field of the record fetched from database;
List<Object[]> parts2=JPA.em().createNativeQuery("select name,collegeName,peopleNum from evaluation_part").getResultList();
Logger.info("The name of first record is :%s", parts2.get(0)[0]);
for(int i=0;i<parts2.size();i++){
//The difference between solution1 and solution2:the previous use constructor in the query and the later transform a record into Object[].
Logger.info("Name from parts1 is: %s", parts1.get(i).name);
Logger.info("Name from parts2 is: %s", parts2.get(i)[0]);
}
renderText("There are %s record in the \'evaluation_part\' table",parts2.size());
}
}
You can use the version of createNativeQuery(...) method that also accepts as argument the Class of the result instance(s):
http://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html#createNativeQuery(java.lang.String, java.lang.Class).
However make sure this actually works, as Play Framework doesn't implement all the features of JPA in it's implementation of the API.

Converting a json string to a native .net object

I need to convert a json to a native .net object using mongodb. The application is written in javascript/mvc.
One of the field is a datetime object and the toJson function in the mongodb driver formats this as: "Modified":{"$date":1319630804846}
I want to parse this json from the client using the same format, but can't find a function that does this.
In Newtonsoft.Json I used this code, but this fails because of the date field:
var jobject = JObject.parse(jsonAsString)
var myObject = jobject.ToObject<myObject>();
But with the mongoDb driver, all I can do is converting the string to a BsonDocument
var buffer = new JsonBuffer(json);
using (BsonReader reader = new JsonReader(buffer))
{
var doc = BsonDocument.ReadFrom(reader);
....
}
The BSON serialization format for DateTime is an Int64 containing the number of milliseconds since Unix Epoch. So if you were to create a DateTime of kind Utc set to jan 1 1970 and then create a TimeSpan with TotalMilliseconds set to the Int64, and add the two together you'd have the date in Utc. The same algorithm could be used in reverse as needed.
If you're using the official .NET driver, you can work with objects without going through the JSON serialization.
Check the following example of how easy this is:
class Child
{
public ObjectId id;
public string name;
public DateTime birthday;
}
class Program
{
static void Main(string[] args)
{
Child m = new Child();
m.name = "Micaiah";
m.birthday = DateTime.Parse("January 1, 2011");
Children.Insert<Child>(m);
foreach (Child kiddo in Children.FindAllAs<Child>())
{
Console.WriteLine("Kiddo: {0} {1}", kiddo.name, kiddo.birthday);
}
Console.ReadLine();
}
static MongoCollection Children
{
get
{
MongoServer s = MongoServer.Create("mongodb://localhost");
return s["demos"]["children"];
}
}
}
Here's the record as stored in MongoDB:
> db.children.findOne()
{
"_id" : ObjectId("4ea821b2dd316c1e70e34d08"),
"name" : "Micaiah",
"birthday" : ISODate("2011-01-01T06:00:00Z")
}
>
Use JSON.Net to de-serialize your Json into a JObject, and send that to MongoDB... if you have more concrete types in C#, you'll want to serialize/deserialize to/from that to JSON... then persist from your concrete object, or JObject.