logo

Java: Test if a Document Exists in a Notes View

I'm writing some Java code in a Notes Agent that processes every single document in a database, apart from those that may exist in certain views.

To test if the document is in a view or not I used this simple function:

private boolean isDocumentInView(lotus.domino.View view, Document doc) 
throws Exception{ if (view==null) return false; //Evaluate returns either a double of 0.0 or 1.0 for this! Dunno why? Vector test = session.evaluate(view.getSelectionFormula(), doc); Double result = (Double)test.firstElement(); return result.equals(1d); }

I seem to remember discussing this before publically, but can't find any reference to it, so I'm blogging now in the hope somebody finds it useful (or in case I need it again at some point -- as the fact evaluate returns a Double has caught me out more than once now).

Update

Jesse Gallagher made a suggestion and did a little investigation to validate that the following method is much more efficient (see comments for more details):

private boolean isDocumentInView(lotus.domino.ViewNavigator nav, Document doc) 
throws Exception{ if (nav==null) return false; return nav.gotoEntry(doc); }

Thanks Jesse! I've updated my code to use this approach instead now.

Obviously you'd define and set the ViewNavigator once at the beginning of the code. You could always simply pass the name of the view as a String to the function and let it get view each time, but that would be plain crazy!

Comments

  1. Hi Jake,

    in formula language there is no "boolean" data type (nor "integer" or "real" etc.). There just is "number" and "string".

    And @True is a number (1), @False is 0.

    As you are evaluating in java, which has strong typing, you will get the number data type which should be able to hold the returned value - which is the double data type.

    To avoid this kind of trouble I tend to use formulas which return strings, e. g. by wrapping the formula into an

    @if (....; "1"; "0");

    Not pretty, but more reliable. I also like to wrap the formula with an @If (@IsError(...); ...), so that I can check the results - instead of the exception handling.

    @Formulas throwing errors are bad, not only in forms - you never know what is going on without catching the errors in every single formula...

    By the way:

    Your formula probably might not work for views with response hierarchies, e. g. selection formulas containing @Responses or @Descendants. But I haven't tested this.

    Hans-Peter

    1. Hi Hans-Peter,

      I bow down to your superior wisdom! Now you've explained it it makes sense. Without the explanation I'd expected the more obvious result of it returning either a 1 or 0 | "1" or "0" | "True" or "False" .

      Thanks for the explanation. I continue to learn.

  2. What could be a use case for this?

    1. It's hard to say what my exact use case was without breaking confidentiality agreements, but this is the 2nd time I've used the same approach. It is useful. Enough for me to think it worthy or posting here.

      Based on the principle that the selection formula for some views is representative of the business logic for a database, it shouldn't be too hard to think of a case where you need to check whether a document is in a view or not.

      Show the rest of this thread

  3. Oh, I like this method. Now it has me thinking about other ways to do it as well... namely, I wonder how the performance would compare to creating a ViewNavigator and calling .gotoEntry(doc). That's always seemed like a bizarre method to me, but I think I found it to be surprisingly fast when I tried it a while back.

    I also kind of wonder how it would work in oddball scenarios like a document qualifying for the selection formula but not visually showing up in the view because its parent isn't there.

    1. Oooh, hadn't thought of that approach. Surely it would be slower to find the document in a ViewNavigator though!? Or would it depend on the complexity of the Selection Formula. If the formula were simply SELECT Form="Foo" then evaluate may win? If the formula were dozens of lines of code, perhaps not?

      I'll leave it with you if you want to look in to it any further ;)

      Show the rest of this thread

    • avatar
    • Phil
    • Thu 23 Feb 2012 08:27 AM

    Can't you just create a view that only shows the documents you require, then process that?

    To take your example above - SELECT !Form="Foo"

    Phil.

    1. Good point. You could, but then you've duplicated the code/logic. If the logic of the view changes you have to change it in the new view too.

      Like everything it's "horses for courses" and "more than one way to swing a cat".

  4. Another approach, which would work the same way for both views and folders is to create an empty NoteCollection object, use NoteCollection.add(doc) to put your document into the collection, and then use NoteCollection.intersect(view). If your document is still in the NoteCollection, it was in the view.

    Or to do it in bulk instead of one document at a time, first define two NoteCollection objects nc1 and nc2, with both containing all documents using the setSelectDocuments(true) and buildCollection() methods. Next call nc2.intersect(view) which gives you only the documents in the view. Finally, call nc1.remove(nc2), which gives you all the documents that were not in the view.

    If you have multiple views and/or folders to work with, you can do it in a loop. I.e., after each remove(), call nc2.clearCollection, then call nc2.add(nc1) so once again you have two identical collections (all docs minus the ones that were removed in previous iterations), and repeat the process of intersecting and removing.

    Note that I haven't tried the bulk approach, but I have a feeling it should be significantly faster because it's never actually opening documents.

Your Comments

Name:
E-mail:
(optional)
Website:
(optional)
Comment:


About This Page

Written by Jake Howlett on Thu 23 Feb 2012

Share This Page

# ( ) '

Comments

The most recent comments added:

Skip to the comments or add your own.

You can subscribe to an individual RSS feed of comments on this entry.

Let's Get Social


About This Website

CodeStore is all about web development. Concentrating on Lotus Domino, ASP.NET, Flex, SharePoint and all things internet.

Your host is Jake Howlett who runs his own web development company called Rockall Design and is always on the lookout for new and interesting work to do.

You can find me on Twitter and on Linked In.

Read more about this site »

More Content