Lesson learned in ReplaceItemValue vs NotesItem

Introduction

In a project I am working on I am modernizing a Domino application with XPages and JAVA MVC. To support the workflow in the application a “main” document must have at least 1 approved “sub” document for 9 mandatory areas. These “sub” documents appear then in a Notes view and an agent is keeping the overview if all 9 areas have approved documents .

The selection formula for this view is something as followed:

SELECT Form=”formA” & status=”40″ & notAuthorized = “”

replaceItemValue

To add a field to a document I normally use ReplaceItemValue as described in the XPages wiki.  The Help in Designer says about this method:

Replaces all items of the specified name with one new item, which is assigned the specified value. If the document does not contain an item with the specified name, this method creates a new item and adds it to the document.

So that sounded that I was good to go. Except… the documents created by my script did not appear in my view.

Document properties

When I compared the documents with ScanEZ / looked at the Document Properties tab / created on output via Document Viewer I could not find an explanation why the documents should not match the View selection formula 😕

Modifying the selection formula to something outrageous like

SELECT Form=”formA” & status=”40″ & notAuthorized != “SOMEOUTRAGEOUSCONDITION”

resulted that the documents appear in the view.

But I would rather like to keep the current data model of the View as is in place so the current code/UI could not become disturbed in any way.

Notes Item

Then I decided to change my code from

doc.replaceItemValue(“notAuthorized”, “”);

into

Item textItem = doc.replaceItemValue(“notAuthorized”, null);

textItem.setValueString(“”);

textItem.setSummary(true);

and I noticed the documents appear now in the Notes View.

When I compare the two methods in the replaceItemValue method the field notAuthorized is empty but has a data-length of 1. In the Item method the field is also empty BUT the data-length is 0.

So something is added to the field. But what?

IsSummary

First I thought perhaps it’s due to the Summary property but in both methods the Summary property set (at least it looks like that).

Here is some more information from Designer Help:

 

The IsSummary property of the new item defaults to true, which means that the item value can be displayed in a view or folder.

So I am wondering if the replaceItemValue (in Java) is properly setting this property or maybe not?

 

User Information class

For a project I needed to check which rights a user has in a database and on documents. The UserBean in the Extension Library did not seem to match my needs since that the rights of the current effective user against the database from which the code is called. In my case the documents reside in different databases than the one serving the Xpages.

Second stop was the UserBean class written by Oliver Busse. This allows me to change the effective username againt a given name.

Name name = session.createName(“a string here”);

The same principle goes for the database.

this.aclLevel = session.getDatabase(“a string here”,”a string here”).queryAccess(this.userNameCanonical);

The aclPriviliges are no part of the original code so I added something as followed:

public final List<String> aclPriviliges = new ArrayList<String>();

if ((accPriv & db.DBACL_CREATE_DOCS) > 0){
if (!aclPriviliges.contains(“DBACL_CREATE_DOCS”)){
aclPriviliges.add(“DBACL_CREATE_DOCS”);
}
}
if ((accPriv & db.DBACL_DELETE_DOCS) > 0){
if (!aclPriviliges.contains(“DBACL_DELETE_DOCS”)){
aclPriviliges.add(“DBACL_DELETE_DOCS”);
}
}

I registered my class as a Managed Bean and I invoke it from the beforepageload event:

<xp:this.beforePageLoad><![CDATA[#{javascript:UserInfo.init(“location of my nsf”,”Ja user name here”);}]]></xp:this.beforePageLoad>

With this I can use it in the same way Oliver demonstrated in his snippet. But I can also check the acl Priviliges:

<xp:div>
<xp:label value=”ACL Priviliges:”></xp:label> 
<xp:label value=”#{javascript:UserInfo.aclPriviliges}”></xp:label>
</xp:div>

Next I wanted to check if a user can edit a document or not. This is not that easy as it might seem. This code is what I took as starting-point. It became this piece of code:

public boolean canEdit(String docId){
boolean canEdit = false;
NotesContext ctx = new NotesContext(null).getCurrent();
Session session = null;
session = getCurrentSession();
try {
Database db = session.getDatabase(“”, this.activeDb);
Document doc = db.getDocumentByUNID(docId);
if(null != doc){
canEdit = ctx.isDocEditable(doc);
}
} catch (NotesException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return canEdit;
}

Unfortunately I cannot set the username, so it runs against against the effective username 😦

I tried to achieve the same functionality with the lock function for documents (which you have to enable on database level) but it fails. Even a given user with Reader access was able to lock a document (name added to $Writers field)

public boolean canWriteDocument(String docId, String userName) {
boolean canWrite = false;
Session session = null;
session = getCurrentSession();
try {
Database db = session.getDatabase(“”, this.activeDb);
if (db.isDocumentLockingEnabled()) {
//Document locking is enabled
Document doc = db.getDocumentByUNID(docId);
if (null != doc){
if (doc.lock(userName)) {
canWrite = true;
doc.unlock();
}
}

} else {
//Document locking is NOT enabled
}

} catch (NotesException e) {
// fail silently
e.printStackTrace();
}
return canWrite;
}

I assume I am doing something wrong but I am not sure what. If you happen to know what then drop a comment.

Happy development 🙂

Add 20 years of experience to your workforce

You can 20 years of experience within IBM Notes and Web development to your workforce by hiring me.

Interested? Read my curriculum vitae on LinkedIn: http://www.linkedin.com/in/patrickkwinten and get in contact.

I am happy to work WITH you !