View Javadoc

1   /*
2    * This file is part of Domingo
3    * an Open Source Java-API to Lotus Notes/Domino
4    * hosted at http://domingo.sourceforge.net
5    *
6    * Copyright (c) 2003-2007 Beck et al. projects GmbH Munich, Germany (http://www.bea.de)
7    *
8    * This library is free software; you can redistribute it and/or
9    * modify it under the terms of the GNU Lesser General Public
10   * License as published by the Free Software Foundation; either
11   * version 2.1 of the License, or (at your option) any later version.
12   *
13   * This library is distributed in the hope that it will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   * Lesser General Public License for more details.
17   *
18   * You should have received a copy of the GNU Lesser General Public
19   * License along with this library; if not, write to the Free Software
20   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21   */
22  
23  package de.bea.domingo.http;
24  
25  import java.io.ByteArrayInputStream;
26  import java.io.IOException;
27  import java.util.ArrayList;
28  import java.util.Calendar;
29  import java.util.Iterator;
30  import java.util.List;
31  import java.util.NoSuchElementException;
32  
33  import javax.xml.parsers.ParserConfigurationException;
34  import javax.xml.parsers.SAXParser;
35  
36  import org.xml.sax.Attributes;
37  import org.xml.sax.SAXException;
38  
39  import de.bea.domingo.DBase;
40  import de.bea.domingo.DDatabase;
41  import de.bea.domingo.DDocument;
42  import de.bea.domingo.DNotesMonitor;
43  import de.bea.domingo.DView;
44  import de.bea.domingo.DViewColumn;
45  import de.bea.domingo.DViewEntry;
46  
47  /***
48   * Http implementation of a Domingo view.
49   *
50   * @author <a href=mailto:kriede@users.sourceforge.net>Kurt Riede</a>
51   */
52  public final class ViewHttp extends BaseHttp implements DView {
53  
54      /*** serial version ID for serialization. */
55      private static final long serialVersionUID = 1484836582323425207L;
56  
57      private String fName;
58  
59      /***
60       * Private Constructor for this class.
61       *
62       * @param theFactory the controlling factory
63       * @param session the session that produced the database
64       * @param database Notes database object
65       * @param monitor the monitor that handles logging
66       * @param forceOpen whether the database should be forced to be open or not
67       * @see lotus.domino.Database
68       */
69      private ViewHttp(final NotesHttpFactory theFactory, final DBase theParent, final String name, final DNotesMonitor monitor) {
70          super(theFactory, theParent, monitor);
71          this.fName = name;
72      }
73  
74      /***
75       * Factory method for instances of this class.
76       *
77       * @param theFactory the controlling factory
78       * @param theParent the parent object
79       * @param name the name of the view
80       * @param monitor the monitor that handles logging
81       *
82       * @return Returns a DDatabase instance of type DatabaseProxy
83       */
84      static DView getInstance(final NotesHttpFactory theFactory, final DBase theParent, final String name,
85              final DNotesMonitor monitor) {
86          return new ViewHttp(theFactory, theParent, name, monitor);
87      }
88  
89      /***
90       * Private accessor method to enclosing view for inner classes.
91       *
92       * @return this
93       */
94      private DView getView() {
95          return this;
96      }
97  
98      /***
99       * Returns the parent database
100      *
101      * @return parent database
102      */
103     private DDatabase getDatabase() {
104         return (DDatabase) getParent();
105     }
106 
107     /***
108      * @see Object#toString()
109      * @return a string representation of the object.
110      */
111     public String toString() {
112         return fName;
113     }
114 
115     /***
116      * {@inheritDoc}
117      *
118      * @see de.bea.domingo.DView#refresh()
119      */
120     public void refresh() {
121         // TODO Auto-generated method stub
122     }
123 
124     /***
125      * {@inheritDoc}
126      *
127      * @see de.bea.domingo.DView#getName()
128      */
129     public String getName() {
130         return fName;
131     }
132 
133     /***
134      * {@inheritDoc}
135      *
136      * @see de.bea.domingo.DView#getDocumentByKey(String, boolean)
137      */
138     public DDocument getDocumentByKey(final String key, final boolean exact) {
139         // TODO Auto-generated method stub
140         return null;
141     }
142 
143     /***
144      * {@inheritDoc}
145      *
146      * @see de.bea.domingo.DView#getDocumentByKey(List, boolean)
147      */
148     public DDocument getDocumentByKey(final List keys, final boolean exact) {
149         // TODO Auto-generated method stub
150         return null;
151     }
152 
153     /***
154      * {@inheritDoc}
155      *
156      * @see de.bea.domingo.DView#getAllDocumentsByKey(String)
157      */
158     public Iterator getAllDocumentsByKey(final String key) {
159         // TODO Auto-generated method stub
160         return null;
161     }
162 
163     /***
164      * {@inheritDoc}
165      *
166      * @see de.bea.domingo.DView#getAllDocumentsByKey(List)
167      */
168     public Iterator getAllDocumentsByKey(final List keys) {
169         // TODO Auto-generated method stub
170         return null;
171     }
172 
173     /***
174      * {@inheritDoc}
175      *
176      * @see de.bea.domingo.DView#getAllDocumentsByKey(String, boolean)
177      */
178     public Iterator getAllDocumentsByKey(final String key, final boolean exact) {
179         // TODO Auto-generated method stub
180         return null;
181     }
182 
183     /***
184      * {@inheritDoc}
185      *
186      * @see de.bea.domingo.DView#getAllDocumentsByKey(List, boolean)
187      */
188     public Iterator getAllDocumentsByKey(final List keys, final boolean exact) {
189         // TODO Auto-generated method stub
190         return null;
191     }
192 
193     /***
194      * {@inheritDoc}
195      *
196      * @see de.bea.domingo.DView#getAllDocumentsByKey(java.util.Calendar)
197      */
198     public Iterator getAllDocumentsByKey(final Calendar key) {
199         return getAllDocumentsByKey(key, false);
200     }
201 
202     /***
203      * {@inheritDoc}
204      *
205      * @see de.bea.domingo.DView#getAllDocumentsByKey(double)
206      */
207     public Iterator getAllDocumentsByKey(final double key) {
208         return getAllDocumentsByKey(key, false);
209     }
210 
211     /***
212      * {@inheritDoc}
213      *
214      * @see de.bea.domingo.DView#getAllDocumentsByKey(int)
215      */
216     public Iterator getAllDocumentsByKey(final int key) {
217         return getAllDocumentsByKey(key, false);
218     }
219 
220     /***
221      * {@inheritDoc}
222      *
223      * @see de.bea.domingo.DView#getAllDocumentsByKey(java.util.Calendar, boolean)
224      */
225     public Iterator getAllDocumentsByKey(final Calendar key, final boolean exact) {
226         // TODO Auto-generated method stub
227         return null;
228     }
229 
230     /***
231      * {@inheritDoc}
232      *
233      * @see de.bea.domingo.DView#getAllDocumentsByKey(double, boolean)
234      */
235     public Iterator getAllDocumentsByKey(final double key, final boolean exact) {
236         // TODO Auto-generated method stub
237         return null;
238     }
239 
240     /***
241      * {@inheritDoc}
242      *
243      * @see de.bea.domingo.DView#getAllDocumentsByKey(int, boolean)
244      */
245     public Iterator getAllDocumentsByKey(final int key, final boolean exact) {
246         // TODO Auto-generated method stub
247         return null;
248     }
249 
250     /***
251      * {@inheritDoc}
252      *
253      * @see de.bea.domingo.DView#getAllDocuments()
254      */
255     public Iterator getAllDocuments() {
256         // TODO Auto-generated method stub
257         return null;
258     }
259 
260     /***
261      * {@inheritDoc}
262      *
263      * @see de.bea.domingo.DView#getAllEntries()
264      */
265     public Iterator getAllEntries() {
266         return new ViewEntryIteratorHttp();
267     }
268 
269     /***
270      * {@inheritDoc}
271      *
272      * @see de.bea.domingo.DView#getAllEntriesReverse()
273      */
274     public Iterator getAllEntriesReverse() {
275         return new ViewEntryIteratorHttp();
276     }
277 
278     private final class ViewEntryIteratorHttp implements Iterator {
279 
280         private static final int DEFAULT_COUNT = 50;
281 
282         /*** Current position in view. */
283         private String fStart = "1";
284 
285         /*** Current position in cache array. */
286         private int fCachePosition = 0;
287 
288         /*** Position of last read entry. */
289         private String fLastPosition = "0";
290 
291         /*** List of cached entries. */
292         private List fViewEntries;
293 
294         public ViewEntryIteratorHttp() {
295             readNextPage(null);
296         }
297 
298         public ViewEntryIteratorHttp(final String startKey) {
299             readNextPage(startKey);
300         }
301 
302         /***
303          * {@inheritDoc}
304          *
305          * @see Iterator#hasNext()
306          */
307         public boolean hasNext() {
308             if (fCachePosition >= fViewEntries.size()) {
309                 readNextPage(null);
310             }
311             return fCachePosition < fViewEntries.size();
312         }
313 
314         /***
315          * {@inheritDoc}
316          *
317          * @see Iterator#next()
318          */
319         public Object next() {
320             if (!hasNext()) {
321                 throw new NoSuchElementException();
322             }
323             return fViewEntries.get(fCachePosition++);
324         }
325 
326         /***
327          * {@inheritDoc}
328          *
329          * @see Iterator#remove()
330          */
331         public void remove() {
332             throw new UnsupportedOperationException();
333         }
334 
335         /***
336          * Reads the next page of view entries from the view.
337          *
338          * @throws IOException if the next page cannot be read
339          */
340         private void readNextPage(final String startKey) {
341             final String path = getDatabase().getFilePath();
342             try {
343                 final String arguments;
344                 if (startKey != null && startKey.length() > 0) {
345                     arguments = "StartKey=" + startKey;
346                 } else {
347                     fStart = increase(fLastPosition);
348                     arguments = "Start=" + fStart + "&Count=" + DEFAULT_COUNT;
349                 }
350                 final String bs = execute(path + "/" + fName, "ReadViewEntries&expandview&" + arguments);
351                 final SAXParser parser = getDSession().getFactory().getSAXParserFactory().newSAXParser();
352                 final ViewEntriesParser viewEntriesParser = new ViewEntriesParser();
353                 // TODO before parsing, check that answer is valid to parse as XML
354                 // todo e.g. check if content-tyoe is XML
355                 // todo e.g. check if it is a login form (has FORM tag with action arg containing 'Login'
356                 parser.parse(new ByteArrayInputStream(bs.getBytes()), viewEntriesParser);
357                 // todo catch parser exception here and signal error
358                 fViewEntries = viewEntriesParser.getViewEntries();
359                 if (fViewEntries.size() > 0) {
360                     DViewEntry viewEntry = (DViewEntry) fViewEntries.get(fViewEntries.size() - 1);
361                     fLastPosition = viewEntry.getPosition('.');
362                 }
363                 fCachePosition  = 0;
364             } catch (IOException e) {
365                 throw new NotesHttpRuntimeException(e);
366             } catch (ParserConfigurationException e) {
367                 throw new NotesHttpRuntimeException(e);
368             } catch (SAXException e) {
369                 throw new NotesHttpRuntimeException(e);
370             }
371         }
372     }
373 
374 
375     /***
376      * Increases a position string to the next position. In case of
377      * hierarchical positions of categoized views, the rightmost position
378      * number is increased.
379      *
380      * Example: <tt>12.3.7</tt> -> <tt>12.3.8</tt>
381      *
382      * @param position a position string
383      * @return increased position string
384      */
385     public static String increase(final String position) {
386         int i = position.lastIndexOf('.');
387         if (i < 0) {
388             return String.valueOf(Integer.parseInt(position) + 1);
389         } else {
390             return position.substring(0, i + 1) + String.valueOf(Integer.parseInt(position.substring(i + 1)) + 1);
391         }
392     }
393 
394     /***
395      * SAX parser for view entries.
396      */
397     private class ViewEntriesParser extends BaseHandler {
398 
399         private List fViewEntries;
400 
401         private ViewEntryHttp fViewEntry;
402 
403         public void startElement(final String namespaceURI, final String localName, final String qName, final Attributes atts)
404                 throws SAXException {
405             if (fViewEntry != null) {
406                 fViewEntry.getParser().startElement(namespaceURI, localName, qName, atts);
407             } else if ("viewentries".equals(qName)) {
408                 fViewEntries = new ArrayList();
409             } else if ("viewentry".equals(qName)) {
410                 fViewEntry = (ViewEntryHttp) ViewEntryHttp.getInstance(getFactory(), getView(), getMonitor());
411                 fViewEntry.getParser().startElement(namespaceURI, localName, qName, atts);
412             } else {
413                 super.startElement(namespaceURI, localName, qName, atts);
414             }
415         }
416 
417         public void endElement(final String uri, final String localName, final String qName) throws SAXException {
418             if ("viewentries".equals(qName)) {
419                 return;
420             } else if ("viewentry".equals(qName)) {
421                 fViewEntry.getParser().endElement(uri, localName, qName);
422                 fViewEntries.add(fViewEntry);
423                 fViewEntry = null;
424             } else if (fViewEntry != null) {
425                 fViewEntry.getParser().endElement(uri, localName, qName);
426             } else {
427                 super.endElement(uri, localName, qName);
428             }
429         }
430 
431         /***
432          * @see BaseHandler#characters(char[], int, int)
433          */
434         public void characters(final char[] ch, final int start, final int length) throws SAXException {
435             if (fViewEntry != null) {
436                 fViewEntry.getParser().characters(ch, start, length);
437             } else {
438                 super.characters(ch, start, length);
439             }
440         }
441 
442         /***
443          * Returns the parsed view entries. Only call this method after parsing
444          * is completed.
445          *
446          * @return parsed view entries
447          */
448         public List getViewEntries() {
449             return fViewEntries;
450         }
451     }
452 
453     /***
454      * {@inheritDoc}
455      *
456      * @see de.bea.domingo.DView#getEntryByKey(String)
457      */
458     public DViewEntry getEntryByKey(final String key) {
459         // TODO Auto-generated method stub
460         return null;
461     }
462 
463     /***
464      * {@inheritDoc}
465      *
466      * @see de.bea.domingo.DView#getEntryByKey(String, boolean)
467      */
468     public DViewEntry getEntryByKey(final String key, final boolean exact) {
469         // TODO Auto-generated method stub
470         return null;
471     }
472 
473     /***
474      * {@inheritDoc}
475      *
476      * @see de.bea.domingo.DView#getEntryByKey(List)
477      */
478     public DViewEntry getEntryByKey(final List keys) {
479         // TODO Auto-generated method stub
480         return null;
481     }
482 
483     /***
484      * {@inheritDoc}
485      *
486      * @see de.bea.domingo.DView#getEntryByKey(List, boolean)
487      */
488     public DViewEntry getEntryByKey(final List keys, final boolean exact) {
489         // TODO Auto-generated method stub
490         return null;
491     }
492 
493     /***
494      * {@inheritDoc}
495      *
496      * @see de.bea.domingo.DView#getAllEntries(DViewEntry)
497      */
498     public Iterator getAllEntries(final DViewEntry entry) {
499         // TODO Auto-generated method stub
500         return null;
501     }
502 
503     /***
504      * {@inheritDoc}
505      *
506      * @see de.bea.domingo.DView#getAllEntriesByKey(String)
507      */
508     public Iterator getAllEntriesByKey(final String key) {
509         return new ViewEntryIteratorHttp(key);
510     }
511 
512     /***
513      * {@inheritDoc}
514      *
515      * @see de.bea.domingo.DView#getAllEntriesByKey(String, boolean)
516      */
517     public Iterator getAllEntriesByKey(final String key, final boolean exact) {
518         // TODO Auto-generated method stub
519         return null;
520     }
521 
522     /***
523      * {@inheritDoc}
524      *
525      * @see de.bea.domingo.DView#getAllEntriesByKey(List)
526      */
527     public Iterator getAllEntriesByKey(final List key) {
528         // TODO Auto-generated method stub
529         return null;
530     }
531 
532     /***
533      * {@inheritDoc}
534      *
535      * @see de.bea.domingo.DView#getAllEntriesByKey(List, boolean)
536      */
537     public Iterator getAllEntriesByKey(final List key, final boolean exact) {
538         // TODO Auto-generated method stub
539         return null;
540     }
541 
542     /***
543      * {@inheritDoc}
544      *
545      * @see de.bea.domingo.DView#getAllCategories()
546      */
547     public Iterator getAllCategories() {
548         // TODO Auto-generated method stub
549         return null;
550     }
551 
552     /***
553      * {@inheritDoc}
554      *
555      * @see de.bea.domingo.DView#getAllCategories(int)
556      */
557     public Iterator getAllCategories(final int level) {
558         // TODO Auto-generated method stub
559         return null;
560     }
561 
562     /***
563      * {@inheritDoc}
564      *
565      * @see de.bea.domingo.DView#getAllCategoriesByKey(String)
566      * @deprecated
567      */
568     public Iterator getAllCategoriesByKey(final String key) {
569         // TODO Auto-generated method stub
570         return null;
571     }
572 
573     /***
574      * {@inheritDoc}
575      *
576      * @see de.bea.domingo.DView#getAllCategoriesByKey(String, int)
577      * @deprecated
578      */
579     public Iterator getAllCategoriesByKey(final String key, final int level) {
580         // TODO Auto-generated method stub
581         return null;
582     }
583 
584     /***
585      * {@inheritDoc}
586      *
587      * @see de.bea.domingo.DView#getAllCategoriesByKey(String, boolean)
588      * @deprecated
589      */
590     public Iterator getAllCategoriesByKey(final String key, final boolean exact) {
591         // TODO Auto-generated method stub
592         return null;
593     }
594 
595     /***
596      * {@inheritDoc}
597      *
598      * @see de.bea.domingo.DView#getAllCategoriesByKey(String, int, boolean)
599      * @deprecated
600      */
601     public Iterator getAllCategoriesByKey(final String key, final int level, final boolean exact) {
602         // TODO Auto-generated method stub
603         return null;
604     }
605 
606     /***
607      * {@inheritDoc}
608      *
609      * @see de.bea.domingo.DView#getAllCategoriesByKey(List)
610      * @deprecated
611      */
612     public Iterator getAllCategoriesByKey(final List key) {
613         // TODO Auto-generated method stub
614         return null;
615     }
616 
617     /***
618      * {@inheritDoc}
619      *
620      * @see de.bea.domingo.DView#getAllCategoriesByKey(List, int)
621      * @deprecated
622      */
623     public Iterator getAllCategoriesByKey(final List key, final int level) {
624         // TODO Auto-generated method stub
625         return null;
626     }
627 
628     /***
629      * {@inheritDoc}
630      *
631      * @see de.bea.domingo.DView#getAllCategoriesByKey(List, boolean)
632      * @deprecated
633      */
634     public Iterator getAllCategoriesByKey(final List key, final boolean exact) {
635         // TODO Auto-generated method stub
636         return null;
637     }
638 
639     /***
640      * {@inheritDoc}
641      *
642      * @see de.bea.domingo.DView#getAllCategoriesByKey(List, int, boolean)
643      * @deprecated
644      */
645     public Iterator getAllCategoriesByKey(final List key, final int level, final boolean exact) {
646         // TODO Auto-generated method stub
647         return null;
648     }
649 
650     /***
651      * {@inheritDoc}
652      *
653      * @see de.bea.domingo.DView#fullTextSearch(java.lang.String)
654      */
655     public int fullTextSearch(final String query) {
656         // TODO Auto-generated method stub
657         return 0;
658     }
659 
660     /***
661      * {@inheritDoc}
662      *
663      * @see de.bea.domingo.DView#fullTextSearch(java.lang.String, int)
664      */
665     public int fullTextSearch(final String query, final int maxdocs) {
666         // TODO Auto-generated method stub
667         return 0;
668     }
669 
670     /***
671      * {@inheritDoc}
672      *
673      * @see de.bea.domingo.DView#clear()
674      */
675     public void clear() {
676         // TODO Auto-generated method stub
677     }
678 
679     /***
680      * {@inheritDoc}
681      *
682      * @see de.bea.domingo.DView#getSelectionFormula()
683      */
684     public String getSelectionFormula() {
685         // TODO Auto-generated method stub
686         return null;
687     }
688 
689     /***
690      * {@inheritDoc}
691      *
692      * @see de.bea.domingo.DView#setSelectionFormula(java.lang.String)
693      */
694     public void setSelectionFormula(final String formula) {
695         // TODO Auto-generated method stub
696     }
697 
698     /***
699      * {@inheritDoc}
700      * @see de.bea.domingo.DView#getColumn(int)
701      */
702     public DViewColumn getColumn(final int i) {
703         // TODO Auto-generated method stub
704         return null;
705     }
706 
707     /***
708      * {@inheritDoc}
709      * @see de.bea.domingo.DView#getColumnCount()
710      */
711     public int getColumnCount() {
712         // TODO Auto-generated method stub
713         return 0;
714     }
715 
716     /***
717      * {@inheritDoc}
718      * @see de.bea.domingo.DView#getColumnNames()
719      */
720     public List getColumnNames() {
721         // TODO Auto-generated method stub
722         return null;
723     }
724 
725     /***
726      * {@inheritDoc}
727      * @see de.bea.domingo.DView#getColumns()
728      */
729     public List getColumns() {
730         // TODO Auto-generated method stub
731         return null;
732     }
733 
734     /***
735      * {@inheritDoc}
736      * @see de.bea.domingo.DView#getAllEntriesByKey(java.util.Calendar, java.util.Calendar, boolean)
737      */
738     public Iterator getAllEntriesByKey(final Calendar start, final Calendar end, final boolean exact) {
739         // TODO Auto-generated method stub
740         return null;
741     }
742 }