Checking what a value is in SSJS - xpages

I have this block of code in SSJS that I'm doing some field validation stuff:
thisDoc is a NoteXspDocument
fld = the name of a field
var thisValue = thisDoc.getValue(fld);
print("Check Text = " + thisValue);
print("Is is a Date " + (thisValue === Date))
when I run it the log has this:
Check Text = 09/10/15 12:00 PM
Is is a Date false
In this code I do not know what the datatype is of the fld which is a field name. I check the backend document and get the NotesItem.Type() and this field is of type text 1280 in the backend, but the NotesXspDocument has a date. I need to determine what the data type is thisValue sure acts like a NotesDateTime object, but I'm doing something wrong somewhere.
I think the issue might be the difference between a NotesDateTime and a java.util.Date but they drive me up the wall.
Further Edit --
The problem is that I have an Array of field names var Fields:Array that I then loop through and get fld = Fields[n] so when I get the value of the field it could be anything Text, Date, Number so when I do var thisValue = thisDoc.getValue(fld) or thisDoc.getItemValue(fld) I need to figure out what kind of value I have. I guess I could put the getItem..... inside a try until I find one that works but that seems like a less than optimum solution.

Try instanceof Date.class. What you've got is not checking the data type of thisValue against the underlying class, instead it's checking the object itself.

Because the field that I am retrieving can be just about anything I use
var thisValue = thisdoc.getValue(fld);
i had a lot of trouble then determining what kind of data I had. It could be a null Date/Number/String So the first thing I did was find out what the backend data type was:
var thisItem:NotesItem = thisDoc.getDocument().getFirstItem(fld);
var type:Integer = thisItem.getType()
This helps somewhat if the field has been previously set, but if it is a new document or the field has not received a value yet it will be type 1280 or text and probably null.
So my fisrt test is for null or "". then it becomes a bit tougher because I need to test for some values. In all my comboboxs I add the text "--- Select ?????" as the first item in the list so I tried to get a substring of "---" but because of variance in the datatype I needed to put that in a try:
try{
if (thisValue.substring(0,3) == "---"){
print("have null Prefix");
rtn = false;
errMsg.push("The field " + fld + " is a Required Field please enter a value");
break;
}catch(e){ etc
I then wrapped the various other datatype tests in trys and now I have it working.
Might be a better way but this works.

Use .getItemValue() to return a vector array, then test the data type. You can also try .getItemValueString() to return a text string or .getItemValueDate() or .getItemValueDateTime() to return date/time.
Since getItemValue() returns an array, use subscript to get the first element:
var thisValue = thisDoc.getItemValue(fld);
var thisIsDate = (thisValue[0] instanceof Date);
print("Check Text = " + thisValue[0]);
print("Is this a Date ? " + thisIsDate;

Related

IBM Lotus - updating room reservation, room name is appended to LOCATION each time

I have a custom XPage java REST api in Lotus to handle reservations, everything is going well so far.
I have one weird "problem" though, whenever I update a meeting, the room name (like Test room/Site) is being appended to the LOCATION in iCalendar string.
The way I'm updating appointments is by finding the entry in user's calendar (NotesCalendar.getEntryByUID), then I call NotesCalendarEntry.read() to get the iCalendar string, I then manually replace values of certain iCalendar fields, like DTSTART to the ones I wish to update (I'm only updating DTSTART, DTEND and SUMMARY). Finally I call NotesCalendarEntry.update(string) to update the event.
It works well, however with each update, the LOCATION field grows bigger and bigger, because the room name is being constantly appended to it, and finally it looks like:
LOCATION: Test Room/Test SiteTest Room/Test SiteTest Room/Test Site
etc.
Am I doing something wrong? How can I prevent this? I don't want to clear the location field each time, because users can put their own location and I'd like to keep it (in that case room name is also being appended to the original location text)
Code:
NotesCalendar cal = session.getCalendar( session.getDbDirectory( session.getServerName() ).openMailDatabase() );
NotesCalendarEntry calEntry = cal.getEntryByUNID(apptUNID); // apptUNID is taken from http json payload
String iCalE = calEntry.read();
// 20190326T160000Z
String dStart = DateUtil.formatICalendar(dtStart);
String dEnd = DateUtil.formatICalendar(dtEnd);
iCalE = iCalE.replace("\\n", ""); // I added this because same was happening to literal \n (not actual line breaks)
StringBuilder sb = new StringBuilder(iCalE);
int StartIndex = iCalE.indexOf("BEGIN:VEVENT"); // DTSTART is also in BEGIN:VTIMEZONE so we need to exclude that
int tmpIndex = iCalE.indexOf("DTSTART", StartIndex) + 7; // 7 = len of DTSTART
int LineBreakIndex = iCalE.indexOf('\n', tmpIndex);
if(iCalE.charAt(LineBreakIndex-1) == '\r')
LineBreakIndex--;
sb.delete(tmpIndex, LineBreakIndex);
sb.insert(tmpIndex, ":" + dStart); // start date
tmpIndex = sb.indexOf("DTEND", StartIndex) + 5;
LineBreakIndex = sb.indexOf(Character.toString('\n'), tmpIndex);
if(sb.charAt(LineBreakIndex-1) == '\r')
LineBreakIndex--;
sb.delete(tmpIndex, LineBreakIndex);
sb.insert(tmpIndex, ":" + dEnd);
calEntry.update(sb.toString());
calEntry.recycle();
Also, can I safely assume that iCalendar lines are always ended with \r\n ? (they currently are, I had some problems with that but I figured it out, I'm not sure if I can safely look for '\r\n' though)
I dont use ical4j because I'm literally only modifying 2 or 3 fields and nothing else.

Xpages SSJS Time part of NotesDateTime does not return its real value

One of my date/Time filed value always return with 12:00:00. I have the same field with another document which always return with the correct value.
I am trying to calculate timeDifferences of these two fields values. Because of this issue calculation always returns wrong. What did i miss?
var hdt1:NotesDateTime = doc.getItemValueDateTimeArray("Tarih").elementAt(0);
var hdt2:NotesDateTime = hhDoc.getItemValueDateTimeArray("Tarih").elementAt(0);
var frk:int=0;
print(hdt1);print(hdt2);print("------------------");
frk = hdt2.timeDifference(hdt1);
doc.getFirstItem("Tarih").getDateTimeValue()

Xpages: how to use viewEnt.getColumnValues() to retrieve all relevant value when export data?

In the Xpage, it will display officer name, officer type and department (I use sessionScope variable to do that). There is a combobox to allow the user to select
the officer type that the user wants to compare. And then a button is used for export the data.
The export data will show the comparison between the document that the selected officer type needs to read and the document that the current officer has been read.
If the officer has read document that matches the selected officer type needs to read, it will show "Document has been read", otherwise, it will
show "Document has not read"
Due this post export data from panel let me know how to export data from panel, I begin to follow the code from the post and modify some code to fulfill the user requirement.
I have two views to do the comparison:
Each officer type needs to read various documents, so there is a view to store the value, the first column is the officer type and the second column is the document
that the officer type should read. The second column is multi value field and I am able to set the Multi-value separator is New Line.
Another view the includes officer name, the related officer type and document read by the officer.(no column for multi value)
I use #DbLookup and for loop to do the comparison and here is part of code:
var officer = sessionScope.Officer;
var officerType = sessionScope.OfficerType;
var showSelectedTypeDoc = #DbLookup(#DbName(),"view1", officerType, 2);
var showUserHasReadDoc= #DbLookup(#DbName(),"view2", officer, 3);
var result = "";
while (viewEnt != null)
{
if(viewEnt.getColumnValues()[1] == officer) //get the value related to the officer in the session
{
writer.write("<tr>");
for(var s = 0; s < showSelectedTypeDoc.length;s++) //loop in view1 first
{
for(var r = 0; r < showUserHasReadDoc.length;r++)//then loop the view2
{
if(showSelectedTypeDoc[s] == showUserHasReadDoc[r])//if value matches between 2 views
{
result = "Document has been read";
}
else
{
result = "Document has not read";
}
}
}
//display the list of the document category related to specific officer type
writer.write("<td>" + viewEnt.getColumnValues()[2] + "</td>"); //Problem occurs here, it only shows the first value, the appearance depends on the loop
writer.write("<td>" + result+ "</td>"); // only display the else part
writer.write("</tr>");
}
}
Actually I suppose
viewEnt.getColumnValues()[2]
will show all the relevant values, however when I export the value, it only display the first value e.g. [first value].
The code
writer.write("<td>" + result+ "</td>");
I review the if condition, it should be fine, but it only shows the else part
I tried
showSelectedTypeDoc[s]
instead of
viewEnt.getColumnValues()[2]
it shows undefined and the appearance depends on the looping.
But if I try
showSelectedTypeDoc[0] //or showSelectedTypeDoc[1], etc
it can show the correct value and the appearance depends on the looping.
However I will not know how many values that the variable stored, so I prefer
showSelectedTypeDoc[s]
to find all relevant values but not successful.
I start to think why it only shows the first value. I revise the code and the view, I guess probably is the multi value column cause the problem. It is because In Louts Client, in the view I only click once to particular value, if the value has multi value, it will show the "tick" symbol to relevant data.
So I would like to know to how to use
viewEnt.getColumnValues()[2]
to retrieve all the data related to a specific value. Grateful for your advice please. Thank you.
getColumnsValues() returns a Java Vector. So the syntax you need to get a specific element in the Vector is getColumnValues().get(2) (which will get the third column).
Getting a column values doesn't need it to be categorised. Categorisation is only required for retrieving the entry, not the column values.
I believe when using the index that static columns (e.g. with formula set to a static value like 1 or "<tr>") are skipped.

mutivalue date field search not working

I have a multivalue field called freeDaysPool which has multiple dates as strings. With the following code, the search does not return anything. If I leave that field out, the search works just fine with the two other fields. I read that I should use CONTAINS with multivalue fields but then I got query not understandable.
I've tried the back-end field as a date field and as a text field and tested all kinds of query combinations and date formats but no luck. Any help is really appreciated.
This is the search button code:
var query = new Array("");
var cTerms = 0;
// Field 1
var search01 = getComponent("searchcustomReservationField01").getValue();
if (#Contains(#Text(search01),"any city")){"";}
else {query[cTerms++] = '[customReservationField01]="' + search01 +'"'};
// Field 2
var search02 = getComponent("searchcustomReservationField02").getValue();
if (#Contains(#Text(search02),"any city")){"";}
else {query[cTerms++] = '[customReservationField02]="' + search02 + '"'};
// Date 1
var formatter = new java.text.SimpleDateFormat("d.M.yyyy");
query[cTerms++] = 'FIELD freeDaysPool = ' + formatter.format(getComponent("searchcustomDateField01").getValue());
// if query is still empty, we fill it with asterisk
if(query == "" || query == null){
query[cTerms++] = "*";
}
// make all as string
qstring = query.join(" AND ").trim();
sessionScope.searchString = qstring;
It will return query as:
[customReservationField01]="Oslo" AND [customReservationField02]="Oslo" AND FIELD freeDaysPool = 6.2.2015
AFAIK date values in formulas (and a query is a formula) have to be noted like
[06.02.2015]
to compare them. Just try to use your formular in the Notes Client to do a fulltext search. If you get results and no errors you found the correct format. That's at least the way I test queries as I'm not able to remind the syntax for years :-D
Thank you for all the help! Seems that Domino keeps the field type as date field even if you change it back to text field (noticed that from the notes FTsearch). I created completely new text field and added the days as strings in dd.MM.yyyy format. I also search them as strings and it works fine.
The changed code bit now looks like this:
// Date 1
var formatter = new java.text.SimpleDateFormat("dd.MM.yyyy");
query[cTerms++] = '[freeDays] CONTAINS "' + formatter.format(getComponent("searchcustomDateField01").getValue())+'"';

Using string in place of property name (LINQ)

I have been able to get the values from tables using linq.
var q=(from app in context.Applicant
where app.ApplicantName=="")
Now what I want is this:
var q=(from app in context.Applicant
where app.stringIhave =="") // so instead of column name I have string which has same name as column.
Is it possible to specify string in Select as this is not sure what I will get in each case, I need different data all the time.
Is it possible to do so?
If no, then I will figure out something else.
Update
I have a GlobalString, which holds the column name of a table.
So when I query that table, I only specify from string which column value I want to get:
var q=(from app in context.Applicants
where app.ID==1013
select GlobalString //which is specifying that I want to get value from which column, as column name is not fixed.
//where GlobalString can have values like: app.FirstName..app.LastName etc
Update1:
var q = context.Applicants.Select("new(it.ApplicantFirstName as FirstName, it.ApplicantLastName as LastName)");
Error Message:
The query syntax is not valid. Near keyword 'AS'
You can use Dynamic Linq (available from NuGet) for that:
var q = context.Applicant.Where(app.stringIhave + " = #0", "");
for select you can try something like this
var q = context.Applicant.Select("new(it.FirstName as FirstName, it.LastName as LastName)");
so you only need construct string for that format

Resources