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