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