]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
e1810a3e4006784a82947d184806f2f633395faf
[tmp/jakarta-migration.git] /
1 package org.collectionspace.services.common.vocabulary;
2
3 import java.util.Iterator;
4 import java.util.List;
5 import java.util.Map;
6
7 import org.collectionspace.services.client.PoxPayloadIn;
8 import org.collectionspace.services.client.PoxPayloadOut;
9 import org.collectionspace.services.common.context.ServiceContext;
10 import org.collectionspace.services.common.document.DocumentException;
11 import org.collectionspace.services.common.document.DocumentNotFoundException;
12 import org.collectionspace.services.common.repository.RepositoryClient;
13 import org.collectionspace.services.common.vocabulary.RefNameServiceUtils.AuthRefConfigInfo;
14 import org.collectionspace.services.config.service.ServiceBindingType;
15 import org.nuxeo.ecm.core.api.DocumentModel;
16 import org.nuxeo.ecm.core.api.DocumentModelList;
17 import org.nuxeo.ecm.core.api.impl.DocumentModelListImpl;
18 import org.nuxeo.ecm.core.api.repository.RepositoryInstance;
19
20 import com.google.common.collect.AbstractIterator;
21
22 /**
23  * A DocumentModelList representing all of the documents that potentially reference an
24  * authority item, found via full text search. This list must be post-processed to
25  * eliminate false positives.
26  *
27  * Documents in this list are lazily fetched one page at a time, as they are accessed through
28  * the list's Iterator, retrieved with the iterator() method. List items may not be accessed
29  * through any other means, including the get() method, and the ListIterator retrieved
30  * with listIterator(). Attempts to do so will result in unspecified behavior.
31  * 
32  */
33 public class LazyAuthorityRefDocList extends DocumentModelListImpl {
34         private static final long serialVersionUID = 1L;
35         
36         private ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx;
37         private RepositoryClient<PoxPayloadIn, PoxPayloadOut> repoClient;
38         private RepositoryInstance repoSession;
39         private List<String> serviceTypes;
40         private String refName;
41         private String refPropName;
42         private Map<String, ServiceBindingType> queriedServiceBindings;
43         private Map<String, List<AuthRefConfigInfo>> authRefFieldsByService;
44         private String whereClauseAdditions;
45         private String orderByClause;
46         private int pageSize;
47         
48         private DocumentModelList firstPageDocList;
49         
50         /**
51          * Creates a LazyAuthorityRefDocList. The method signature is modeled after
52          * RefNameServiceUtils.findAuthorityRefDocs (the non-lazy way of doing this).
53          * 
54          * @param ctx
55          * @param repoClient
56          * @param repoSession
57          * @param serviceTypes
58          * @param refName
59          * @param refPropName
60          * @param queriedServiceBindings
61          * @param authRefFieldsByService
62          * @param whereClauseAdditions
63          * @param orderByClause
64          * @param pageSize                                              The number of documents to retrieve in each page
65          * @param computeTotal
66          * @throws DocumentException
67          * @throws DocumentNotFoundException
68          */
69         public LazyAuthorityRefDocList(
70                 ServiceContext<PoxPayloadIn, PoxPayloadOut> ctx,
71                 RepositoryClient<PoxPayloadIn, PoxPayloadOut> repoClient,
72                 RepositoryInstance repoSession, List<String> serviceTypes,
73                 String refName,
74                 String refPropName,
75                 Map<String, ServiceBindingType> queriedServiceBindings,
76                 Map<String, List<AuthRefConfigInfo>> authRefFieldsByService,
77                 String whereClauseAdditions,
78                 String orderByClause,
79                 int pageSize,
80                 boolean computeTotal) throws DocumentException, DocumentNotFoundException {
81
82                 this.ctx = ctx;
83                 this.repoClient = repoClient;
84                 this.repoSession = repoSession;
85                 this.serviceTypes = serviceTypes;
86                 this.refName = refName;
87                 this.refPropName = refPropName;
88                 this.queriedServiceBindings = queriedServiceBindings;
89                 this.authRefFieldsByService = authRefFieldsByService;
90                 this.whereClauseAdditions = whereClauseAdditions;
91                 this.orderByClause = orderByClause;
92                 this.pageSize = pageSize;
93
94                 // Fetch the first page immediately. This is necessary so that calls
95                 // to totalSize() will work immediately. The computeTotal flag is passed
96                 // into this initial page fetch. There's no need to compute totals
97                 // when fetching subsequent pages.
98                 
99                 firstPageDocList = fetchPage(0, computeTotal);
100         }
101
102         /**
103          * Retrieves a page of authority references.
104          * 
105          * @param pageNum               The page number
106          * @param computeTotal  
107          * @return
108          * @throws DocumentNotFoundException
109          * @throws DocumentException
110          */
111         private DocumentModelList fetchPage(int pageNum, boolean computeTotal) throws DocumentNotFoundException, DocumentException {
112                 return RefNameServiceUtils.findAuthorityRefDocs(ctx, repoClient, repoSession,
113                         serviceTypes, refName, refPropName, queriedServiceBindings, authRefFieldsByService,
114                         whereClauseAdditions, orderByClause, pageSize, pageNum, computeTotal);
115         }
116                 
117         @Override
118         public long totalSize() {
119                 // Return the totalSize from the first page of documents.
120                 return firstPageDocList.totalSize();
121         }
122
123         @Override
124         public Iterator<DocumentModel> iterator() {
125                 // Create a new iterator that starts with the first page of documents.
126                 return new Itr(0, firstPageDocList);
127         }
128         
129         /**
130          * An iterator over a LazyAuthorityRefDocList. The iterator keeps one
131          * page of documents in memory at a time, and traverses that page until
132          * no items remain. A new page is fetched only when the current page is
133          * exhausted.
134          *
135          */
136         private class Itr extends AbstractIterator<DocumentModel> {
137                 private int currentPageNum = 0;
138                 private DocumentModelList currentPageDocList;
139                 private Iterator<DocumentModel> currentPageIterator;
140                 
141                 /**
142                  * Creates a new iterator.
143                  * 
144                  * @param currentPageNum                The initial page number
145                  * @param currentPageDocList    The documents in the initial page
146                  */
147                 protected Itr(int pageNum, DocumentModelList pageDocList) {
148                         setCurrentPage(pageNum, pageDocList);
149                 }
150
151                 /**
152                  * Changes the current page.
153                  * 
154                  * @param pageNum               The new page number
155                  * @param pageDocList   The documents in the new page
156                  */
157                 private void setCurrentPage(int pageNum, DocumentModelList pageDocList) {
158                         this.currentPageNum = pageNum;
159                         this.currentPageDocList = pageDocList;
160                         this.currentPageIterator = pageDocList.iterator();
161                 }
162                 
163                 @Override
164                 protected DocumentModel computeNext() {
165                         // Find the next document to return, looking first in the current
166                         // page. If the current page is exhausted, fetch the next page.
167                         
168                         if (currentPageIterator.hasNext()) {
169                                 // There is still an element to return from the current page.
170                                 return currentPageIterator.next();
171                         }
172                         
173                         // The current page is exhausted.
174                         
175                         if (currentPageDocList.size() < pageSize) {
176                                 // There are no more pages.
177                                 return endOfData();
178                         }
179                         
180                         // There may be more pages. Try to fetch the next one.
181                         
182                         int nextPageNum = currentPageNum + 1;
183                         DocumentModelList nextPageDocList = null;
184                         
185                         try {
186                                 nextPageDocList = fetchPage(nextPageNum, false);
187                         }
188                         catch(DocumentException e) {}
189                         
190                         if (nextPageDocList == null || nextPageDocList.size() == 0) {
191                                 // There are no more pages.
192                                 return endOfData();
193                         }
194
195                         // There is another page. Make it the current page.
196                         
197                         setCurrentPage(nextPageNum, nextPageDocList);
198                         
199                         if (currentPageIterator.hasNext()) {
200                                 return currentPageIterator.next();
201                         }
202
203                         // Shouldn't get here.
204
205                         return endOfData();
206                 }
207         }
208 }