I am using the Lotus Notes 6.5.1 Java API to read an .nsf file. Every document in the .nsf file has multiple document history. While traversing through the documents in the .nsf file using the Lotus Notes Java API I am getting all the document versions as separate documents.
How do I ensure only the latest version of each document is retrieved by Lotus Notes? Is there a way to uniquely identify a document and all its version history as its children?
There is a built in feature for versioning documents in Notes Domino. Depending on hows it's configured in the database design (and assuming the database developer didn't roll their own) the versions will either be responses to an original parent, or the other way round, where new versions become the parent, with older versions being responses.
All this does however is to set up a response hierarchy in the database for you automatically when you edit the documents. How the rest of the database design interacts with this hierarchy is up to the developer.
What you probably want to do is create a view that only shows documents at the top of the response hierarchy. You can then traverse that view and know that the documents you get from it are the latest versions.
So if you have documents created with a form "Article" the view selection formula would be.
SELECT form*="Article" & !#IsAvailable($ref)
This selects all Article documents that are not responses. Now in code you can simply open the view and traverse it.
Once you have a handle on a document you can get its immediate child responses through
doc.getResponses()
This returns a DocumentCollection that you can recurse down finding responses to responses. You can't get a parent document directly. You first need to get its id with doc.getParentDocumentUNID() and then call db.getDocumentByUNID(). Of course you can combine that:
db.getDocumentByUNID(doc.getParentDocumentUNID())
In any case, you will have to look at what your database is actually doing, how it was originally designed and fit in with that.
Related
Hoping someone can point me in the correct direction for an XPages application we are writing inside the Domino Client (Notes?) viewer.
I have a view of documents which is being returned, this view has categories on it, and shows fine as this in an XPage, we now apply a filter to the view to limit it to specific owners of the documents, but as soon as we apply the filter, the categories disappear, which means we are left with a long list of documewnts, but unsorted - is there any way to display a filtered view in a categorized manner, on an XPage.
Moving further down my list, I also need to be able to select these documents (and one or many owners) to send to an Lotus Agent which will then create a JSON document to be sent to our friends at DocuSign requesting signatures from the selected owners on the selected documents. I'm not sure what an Agent is yet, but that is the goal ...
Caveat: I'm not a Domino developer, so excuse me if some of the terminology is incorrect.
Categorised views are a very "Notes" construct. When you filter a view, it will only show documents, but not categories. While they are practical in the back, they are cumbersome in the UI.
There are a few design considerations how to tame them in a webUI. However if your users love them, you might consider to flatten them out and recreate the categories in the UI (client side) only.
The actual better way for your use case: add another view that is firstly categorised by the owner and secondly by your category. Use the category filter of the view control to limit the documents to that author. This should do the trick. Eventually use one of the controls from the extension library.
For the agent: don't bother, that's "old Notes speak". An agent would be a piece of code (LotusScript or Java, but since you do web interaction: Java) that gets triggered by an event: manual, on schedule, on document create/update (with some delay).
Since you are in an XPage, you have easier options at your disposal: create a Bean that has the JSON format you need, add a method that takes a Notes document as parameter to populate it, something like public void populate(final Document doc) {...} and use e.g. the GSON library to simply marshall them to JSON (or a collection of them). The GSON library probably is on a current Domino, I put it there as part of VoP 1.0.
Then use a managed bean to talk to Dokusign. When traveling down the managed bean road is is much easier to test than trying to mess with agents.
Hope that helps and ask more questions! (Check the Learning XPages Cheatsheet too)
In several mail-in and regular databases we have documents that appear to be "uneditable" - i.e. edit them and the edits appear not to save. In fact what is happening is that both the original and the edited doc are being saved because something has switched on "versioning". Needless to say this confuses users quite a lot.
It appears you can only tell versioning is enabled by looking inside the document properties for a field called $VersionOpt.
The form designs have versioning set to None, so something must be setting $VersionOpt.. but what might do that? Is there anything in a regular 8.5.3 mail client that sets document versioning? Any other ideas how this can happen?
(This link explains the background to Notes versioning - http://gg-lnotes.blogspot.co.uk/2010/04/ways-to-do-version-controllingtracking.html)
Based on the comments, my best guess is that you have one or more users drafting their messages in a Notes application built with a template that supports versioning (possibly the Document Library, but it could be something custom) and using a programmed action that calls #MailSend to submit them to the mail-in database. That's going to take the note intact, add the required fields (e.g., SendTo, etc.) for mailing, and drop it into mail.box, complete with all items that the application template's code had created.
(The only other possibility I can conceive of is that you have some add-on software on one of your servers that is hooking the router and adding the $VersionOpt item based on something it sees in certain messages, but that seems very far-fetched. I've never heard of a mail add-in that would do that.)
In any case, the solution to the problem would be to add an agent to the mail-in databases, triggered by the "Before new mail arrives" event, to remove the item. I.e., FIELD $VersionOpt = #DeleteField;
If a user creates a Notes 'memo' message using 'stationery', the new note can be created with a version control field. If this Notes 'memo' is then mailed in to the mail-in db, it will recieve the message with the version control field '$VersionOpt'. See this answer in an old forum post:
http://www-10.lotus.com/ldd/nd6forum.nsf/ShowMyTopicsAllFlatweb/92a576fbe203b781852573af00630b78?OpenDocument
There are also old technotes referring to this issue.
The solution is to delete the field using a background agent or otherwsie arrange to delete the field.
I am developing a database on Lotus Designer 8.5 environment with LotusScript and LotusFormula.
Is there any possibilities on get a list of recently opened documents (for example last five) in a Lotus Notes database ? My purpose is to provide an embedded view showing the recent documents opened by current user on the current database, which will act like some kind of history view.
Please advise
Use a folder categorized by username. Add the current document in PostOpen event to folder with document.PutInFolder(folderName) and remove the oldest document from folder with document.RemoveFromFolder(folderName)
This way you don't need to edit the documents and can show the last visited documents for a user in an embedded view.
As an alternative you can use user specific folders with option "Shared, private on first use".
I have that functionality in one of my databases.
I just added some code in the QueryOpen event of the form to store the UNID of the document in a profile document linked to the specific user. The values are stored in a multi value field, and my code removes the oldest entry when the number of entries I want to store is exceeded.
The user can actually set that number themselves in teh applications settings, 5 is default but they can make it more or less.
I built a class for this, makes it very easy to modify later, and to implement it in different forms, for different document types.
I then built a method to expose the last documents to the user, using a dropdown box as you can see below. Since you only wwant/need the five (or perhas ten) last documents, no need to use a view.
I have a SharePoint document library I am working on. It has a list of document sets. Each document set has a few fields that are marked as "Shared" so that they can be inherited by the documents inside.
When I upload a document inside a form opens and all the fields on the form are pre-filled with the shared values of the corresponding columns. But when I use create document from template, it opens the template in the corresponding Office application but the document property fields are empty and not read-only which is against the requirements of this project. I require them to be synced and filled exactly like when a document is uploaded.
There is one thing though. The user can fill any value he wants in those fields and they will still be saved a synced copy from parent in the library discarding what the user filled in, which is good, but why not show those values up in the document in the first place?
Anyone has experience in handling this please help. I have searched a lot on the internet but either my keywords are wrong or no one has had this problem before.
SharePoint version: 2010 Server
Office version: 2010 Professional
It sounds like you need a simple event reciever, which fire on itemadded. It would then go back up the tree to find the document set. Capture which properties are marked as shared. Adjust the item that is being added to force the values.
Probably 8 lines of code
I am doing "traditional" lotus notes programming (same since R5) and need to implement linking between 2 document types (forms) residing in different databases.
Document of type (A) in database (A) can reference several documents of type (B) in database (B).
And document (B) should also display its relationships with document (A), as document (B) can be related to different documents (A).
We have Many to Many relationship.
At the moment it is implemented on one side only (one to many):
Form of Document (A) contains embedded view of special
"link" documents residing in database A. This link documents are created by lotusScript when user selects documents from database (B). When user clicks on an item in this embedded view, it opens document (B).
Client wants to be able to edit this relationship on any side, so that if he edits it in form (A), form (B) is updated.
Form (B) is supposed to have the same kind of embedded view or a list of associated documents of type (A)
What is the best way to implement it?
Client's infrastracture is Lotus Domino 8.5.2 + Lotus Notes 8.5.2, so theoretically, composite applications approach may be an option.
The reason why I ask this question is that as far as I understand there is no good way in Notes to embed a view from another database.
The requirement is that the database should be present on workspace to be displayed in some sort of dodgy list.
It would be great to be able to specify target database for embedded view by server and replicaID, but instead we have a weird list of random workspace databases.
The main problem is that Notes wasn't designed to handle relationships like that between databases (nor anything besides parent child relationships for that matter). So the solution will have to be a creative one.
A couple of (off-the wall, potentially awful) ideas come to mind. One is to store the references in the documents themselves, and update them whenever the document is saved. That could all be done in LotusScript, and would require searching through the other database's documents to update their references.
Upside is that the performance when reading the documents would be excellent. There'd be no issues while reading Database A if Database B was unavailable. It keeps data local to each database. The downsides include the likelihood of save conflicts and the danger that references could get out of sync if documents aren't "saved" but instead are updated via agents, etc.
Another thought is to use agents to manage the links on a scheduled basis. If you don't need real-time up-to-date references, you could run an agent that scans Database B and updates the references in Database A. With this method you could choose either to update the Database A documents themselves - or - as it sounds like you've already done, create a set of link documents that show up in an embedded view. The latter eliminates the save conflict problem.
One more idea is to hide any references when you open a document in Database A, but provide a button to "show" or "update" references. When you click that button, it fires off LotusScript to search Database B and build a list on the fly. This would probably work quickly with less than 10,000 documents. That function could update the link documents you store on the same database which feed the embedded view.
Hope this helps!
What is the best way to implement it?
As you mention creating a composite application may allow you to do this, but would be restricted to windows rather then design level in the form.
eg.
[Window A] --- trigger ---> [Window B]
If you are not familiar with this system I did a tutorial which explains the basics.
http://www-10.lotus.com/ldd/compappwiki.nsf/dx/ibm-my-first-wire
Although the tutorial calls back to the same database, it is easy enough to point to a different one.
Personally I'd do it through XPages. I personally find it much easier to implement then through classic style notes design/comp apps. It will also allow you to display design elements within the same screen area.
As you've already heard, Lotus Notes has no referential integrity constraints built-in, you have to do it yourself.
I wouldn't be relying on document links as they're geared around UNID's which can change if you cut and paste the same document, thus losing the link. Try this,
1/ Create an "ID" field on each document. You can populate it by using #Unique in a computed field to generate an ID, and save that to the documents in both databases. You can create an agent to do this in lotusScript (LS), or formula. (Consider using the evaluate statement if doing in LS)
2/ Create a lookup view in each database that lists the documents by the new ID (don't forget to set the "sort order" of the ID column.
3/ Using an action button that can be configured for both databases, you can create a LS function that will open the the opposing databases view and return the ID field. (NotesUIWorkspace.pickliststrings would be the simplest way to pick the documents, otherwise you could build a dialogbox. Store the list of results in a field called "linkedID" as multi-value list.
4/ There may be more info that you want to store like document title or author, so you'll need to then get a handle to those documents using getdocumentbykey and then interrogating the fields you'll need to display information on screen.
5/ You can then also add a new field on the target documents you're referring to, call it "referrerID", which is a list of documents that reference the current document. This will maintain the two-way relationship.
The field that stores links must be a multi-valued field, otherwise it gets quite cumbersome to loop through list of linked document ID's and manage them.
This approach uses a static key so you can copy databases around without losing the relationships between documents the user has invested time in producing. You can (and probably will) lose those relationships if you rely on document universal ID's (described well in the #documentUniqueID documentation), if you cut and paste the document, or copy the database somewhere else they become new documents despite copying the same fields, and will be assigned a new universal ID, any document links for the old document will be invalid.
If the information you're displaying from the other database changes, you'll need to be able to refresh that data regularly, so consider writing a scheduled agent that can do the look up and refresh the relevant fields.
If the user intends to un-link or change the relationships between documents, then you'll need to add functions that loop through the key fields and keep the lists consistent with what the user is doing. So, like I said, Lotus Notes' flat data structure requires you manage all integrity constraints yourself.
If you want to get a little fancy you can use embedded views as they do support references from another database on the same server. Some tips about handling it in LotusScript here. And use an additional view that categorises your data by the referring ID. Embedded views are ok, as long as the view they're based on is not too big, otherwise it may affect the performance of the form that it is embedded into.