]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
4ff9cabf691cacf20cc9ec5a8ed5e9af55ff8542
[tmp/jakarta-migration.git] /
1 /**
2  * This document is a part of the source code and related artifacts
3  * for CollectionSpace, an open source collections management system
4  * for museums and related institutions:
5  *
6  * http://www.collectionspace.org
7  * http://wiki.collectionspace.org
8  *
9  * Copyright © 2009 Regents of the University of California
10  *
11  * Licensed under the Educational Community License (ECL), Version 2.0.
12  * You may not use this file except in compliance with this License.
13  *
14  * You may obtain a copy of the ECL 2.0 License at
15  * https://source.collectionspace.org/collection-space/LICENSE.txt
16  *
17  * Unless required by applicable law or agreed to in writing, software
18  * distributed under the License is distributed on an "AS IS" BASIS,
19  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
20  * See the License for the specific language governing permissions and
21  * limitations under the License.
22  */
23 package org.collectionspace.services.client.test;
24
25 import java.util.Arrays;
26 import java.util.ArrayList;
27 import java.util.List;
28
29 import javax.ws.rs.core.MediaType;
30 import javax.ws.rs.core.Response;
31
32 import org.collectionspace.services.CollectionObjectJAXBSchema;
33 import org.collectionspace.services.client.AbstractCommonListUtils;
34 import org.collectionspace.services.client.CollectionObjectClient;
35 import org.collectionspace.services.client.CollectionSpaceClient;
36 import org.collectionspace.services.client.PayloadOutputPart;
37 import org.collectionspace.services.client.PoxPayloadOut;
38 import org.collectionspace.services.collectionobject.CollectionobjectsCommon;
39 import org.collectionspace.services.jaxb.AbstractCommonList;
40
41 //import org.jboss.resteasy.client.ClientResponse;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44 import org.testng.Assert;
45 import org.testng.annotations.AfterClass;
46 import org.testng.annotations.BeforeClass;
47 import org.testng.annotations.Test;
48
49 /**
50  * CollectionObjectSearchTest, carries out tests of keyword search functionality
51  * against a deployed and running CollectionObject Service.
52  * 
53  * $LastChangedRevision: 1327 $ $LastChangedDate: 2010-02-12 10:35:11 -0800
54  * (Fri, 12 Feb 2010) $
55  */
56 public class CollectionObjectSearchTest extends BaseServiceTest<AbstractCommonList> {
57
58         /** The logger. */
59         private final String CLASS_NAME = CollectionObjectSearchTest.class
60                         .getName();
61         private final Logger logger = LoggerFactory.getLogger(CLASS_NAME);
62         final static String IDENTIFIER = getSystemTimeIdentifier();
63         final static String KEYWORD_SEPARATOR = " ";
64         final long numNoiseWordResources = 10;
65         final double pctNonNoiseWordResources = 0.5;
66         // Use this to keep track of resources to delete
67         private List<String> allResourceIdsCreated = new ArrayList<String>();
68
69         // Constants for data used in search testing
70
71         // Test keywords unlikely to be encountered in actual collections data,
72         // consisting of the names of mythical creatures in a 1970s role-playing
73         // game, which result in very few 'hits' in Google searches.
74         final static String KEYWORD = "Tsolyani" + IDENTIFIER;
75         final static List<String> TWO_KEYWORDS = Arrays.asList(new String[] {
76                         "Cheggarra" + IDENTIFIER, "Ahoggya" + IDENTIFIER });
77         final static List<String> TWO_MORE_KEYWORDS = Arrays.asList(new String[] {
78                         "Karihaya" + IDENTIFIER, "Hlikku" + IDENTIFIER });
79         final static String NOISE_WORD = "Mihalli + IDENTIFIER";
80         // Test Unicode UTF-8 term for keyword searching: a random sequence,
81         // unlikely to be encountered in actual collections data, of two USASCII
82         // characters followed by four non-USASCII range Unicode UTF-8 characters:
83         //
84         // Δ : Greek capital letter Delta (U+0394)
85         // Ж : Cyrillic capital letter Zhe with breve (U+04C1)
86         // Ŵ : Latin capital letter W with circumflex (U+0174)
87         // Ω : Greek capital letter Omega (U+03A9)
88         final String UTF8_KEYWORD = "to" + '\u0394' + '\u04C1' + '\u0174'
89                         + '\u03A9';
90         // Non-existent term unlikely to be encountered in actual collections
91         // data, consisting of two back-to-back sets of the first letters of
92         // each of the words in a short pangram for the English alphabet.
93         final static String NON_EXISTENT_KEYWORD = "jlmbsoqjlmbsoq";
94
95         @Override
96         protected String getServiceName() {
97                 throw new UnsupportedOperationException(); // FIXME: REM - See // http://issues.collectionspace.org/browse/CSPACE-3498
98         }
99
100         @Override
101         protected String getServicePathComponent() {
102                 throw new UnsupportedOperationException(); // FIXME: REM - See // http://issues.collectionspace.org/browse/CSPACE-3498
103         }
104
105         /*
106          * (non-Javadoc)
107          * 
108          * @see
109          * org.collectionspace.services.client.test.BaseServiceTest#getClientInstance
110          * ()
111          */
112         @Override
113         protected CollectionSpaceClient getClientInstance() throws Exception {
114                 return new CollectionObjectClient();
115         }
116
117         @Override
118         protected CollectionSpaceClient getClientInstance(String clientPropertiesFilename) throws Exception {
119                 return new CollectionObjectClient(clientPropertiesFilename);
120         }
121         
122         /**
123          * Creates one or more resources containing a "noise" keyword, which should
124          * NOT be retrieved by keyword searches.
125          * 
126          * This also helps ensure that searches will not fail, due to a
127          * database-specific constraint or otherwise, if the number of records
128          * containing a particular keyword represent too high a proportion of the
129          * total number of records.
130          * @throws Exception 
131          */
132         @BeforeClass(alwaysRun = true)
133         public void setup() throws Exception {
134                 if (logger.isDebugEnabled()) {
135                         logger.debug("Creating " + numNoiseWordResources
136                                         + " 'noise word' resources ...");
137                 }
138                 createCollectionObjects(numNoiseWordResources, NOISE_WORD);
139         }
140
141         // ---------------------------------------------------------------
142         // Search tests
143         // ---------------------------------------------------------------
144         // Success outcomes
145
146         @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class, groups = { "advancedSearch" })
147         public void advancedSearch(String testName) throws Exception {
148                 // Create one or more keyword retrievable resources, each containing
149                 // a specified keyword.
150                 String theKeyword = KEYWORD + "COW";
151                 long numKeywordRetrievableResources = 1;
152                 createCollectionObjects(numKeywordRetrievableResources, theKeyword);
153
154                 // Set the expected status code and group of valid status codes
155                 testSetup(STATUS_OK, ServiceRequestType.SEARCH);
156
157                 // Send the search request and receive a response
158                 String propertyName = CollectionObjectClient.SERVICE_COMMON_PART_NAME + ":" +
159                         CollectionObjectJAXBSchema.DISTINGUISHING_FEATURES;
160                 String propertyValue = theKeyword;
161                 Response res = doAdvancedSearch(propertyName, propertyValue, "=");
162                 try {
163                         int statusCode = res.getStatus();
164         
165                         // Check the status code of the response: does it match
166                         // the expected response(s)?
167                         if (logger.isDebugEnabled()) {
168                                 logger.debug(testName + ": status = " + statusCode);
169                         }
170                         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
171                                         invalidStatusCodeMessage(testRequestType, statusCode));
172                         Assert.assertEquals(statusCode, testExpectedStatusCode);
173         
174                         // Verify that the number of resources matched by the search
175                         // is identical to the expected result
176                         long NUM_MATCHES_EXPECTED = numKeywordRetrievableResources;
177                         long numMatched = getNumMatched(res, NUM_MATCHES_EXPECTED, testName);
178                         Assert.assertEquals(numMatched, NUM_MATCHES_EXPECTED);
179                 } finally {
180                         res.close();
181                 }
182         }
183
184         @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class, groups = { "oneKeyword" })
185         public void searchWithOneKeyword(String testName) throws Exception {
186                 // Create one or more keyword retrievable resources, each containing
187                 // a specified keyword.
188                 long numKeywordRetrievableResources = (long) (numNoiseWordResources * pctNonNoiseWordResources);
189                 if (logger.isDebugEnabled()) {
190                         logger.debug("Creating " + numKeywordRetrievableResources
191                                         + " keyword-retrievable resources ...");
192                 }
193                 createCollectionObjects(numKeywordRetrievableResources, KEYWORD);
194
195                 // Set the expected status code and group of valid status codes
196                 testSetup(STATUS_OK, ServiceRequestType.SEARCH);
197
198                 // Send the search request and receive a response
199                 Response res = doSearch(KEYWORD);
200                 try {
201                         int statusCode = res.getStatus();
202         
203                         // Check the status code of the response: does it match
204                         // the expected response(s)?
205                         if (logger.isDebugEnabled()) {
206                                 logger.debug(testName + ": status = " + statusCode);
207                         }
208                         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
209                                         invalidStatusCodeMessage(testRequestType, statusCode));
210                         Assert.assertEquals(statusCode, testExpectedStatusCode);
211         
212                         // Verify that the number of resources matched by the search
213                         // is identical to the expected result
214                         long NUM_MATCHES_EXPECTED = numKeywordRetrievableResources;
215                         long numMatched = getNumMatched(res, NUM_MATCHES_EXPECTED, testName);
216                         Assert.assertEquals(numMatched, NUM_MATCHES_EXPECTED);
217                 } finally {
218                         res.close();
219                 }
220         }
221
222         @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
223         public void searchWithTwoKeywordsInSameField(String testName)
224                         throws Exception {
225                 // Create one or more keyword retrievable resources, each containing
226                 // two specified keywords.
227                 long numKeywordRetrievableResources = (long) (numNoiseWordResources * pctNonNoiseWordResources);
228                 if (logger.isDebugEnabled()) {
229                         logger.debug("Creating " + numKeywordRetrievableResources
230                                         + " keyword-retrievable resources ...");
231                 }
232                 boolean keywordsInSameField = true;
233                 createCollectionObjects(numKeywordRetrievableResources, TWO_KEYWORDS,
234                                 keywordsInSameField);
235
236                 // Set the expected status code and group of valid status codes
237                 testSetup(STATUS_OK, ServiceRequestType.SEARCH);
238
239                 // Search using both terms
240
241                 // Send the search request and receive a response
242                 Response res = doSearch(TWO_KEYWORDS);
243                 try {
244                         int statusCode = res.getStatus();
245         
246                         // Check the status code of the response: does it match
247                         // the expected response(s)?
248                         if (logger.isDebugEnabled()) {
249                                 logger.debug(testName + ": status = " + statusCode);
250                         }
251                         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
252                                         invalidStatusCodeMessage(testRequestType, statusCode));
253                         Assert.assertEquals(statusCode, testExpectedStatusCode);
254         
255                         // Verify that the number of resources matched by the search
256                         // is identical to the expected result
257                         long NUM_MATCHES_EXPECTED = numKeywordRetrievableResources;
258                         long numMatched = getNumMatched(res, NUM_MATCHES_EXPECTED, testName);
259                         Assert.assertEquals(numMatched, NUM_MATCHES_EXPECTED);
260                 } finally {
261                         res.close();
262                 }
263
264                 // Search using a single term
265
266                 // Send the search request and receive a response
267                 res = doSearch(TWO_KEYWORDS.get(0));
268                 try {
269                         int statusCode = res.getStatus();
270         
271                         // Check the status code of the response: does it match
272                         // the expected response(s)?
273                         if (logger.isDebugEnabled()) {
274                                 logger.debug(testName + ": status = " + statusCode);
275                         }
276                         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
277                                         invalidStatusCodeMessage(testRequestType, statusCode));
278                         Assert.assertEquals(statusCode, testExpectedStatusCode);
279         
280                         // Verify that the number of resources matched by the search
281                         // is identical to the expected result
282                         long NUM_MATCHES_EXPECTED = numKeywordRetrievableResources;
283                         long numMatched = getNumMatched(res, NUM_MATCHES_EXPECTED, testName);
284                         Assert.assertEquals(numMatched, NUM_MATCHES_EXPECTED);
285                 } finally {
286                         res.close();
287                 }
288         }
289
290         @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
291         public void searchWithTwoKeywordsAcrossTwoFields(String testName)
292                         throws Exception {
293                 // Create one or more keyword retrievable resources, each containing
294                 // two specified keywords.
295                 long numKeywordRetrievableResources = 5;
296                 if (logger.isDebugEnabled()) {
297                         logger.debug("Creating " + numKeywordRetrievableResources
298                                         + " keyword-retrievable resources ...");
299                 }
300                 boolean keywordsInSameField = false;
301                 createCollectionObjects(numKeywordRetrievableResources,
302                                 TWO_MORE_KEYWORDS, keywordsInSameField);
303
304                 // Set the expected status code and group of valid status codes
305                 testSetup(STATUS_OK, ServiceRequestType.SEARCH);
306
307                 // Search using both terms
308
309                 // Send the search request and receive a response
310                 Response res = doSearch(TWO_MORE_KEYWORDS);
311                 try {
312                         int statusCode = res.getStatus();
313         
314                         // Check the status code of the response: does it match
315                         // the expected response(s)?
316                         if (logger.isDebugEnabled()) {
317                                 logger.debug(testName + ": status = " + statusCode);
318                         }
319                         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
320                                         invalidStatusCodeMessage(testRequestType, statusCode));
321                         Assert.assertEquals(statusCode, testExpectedStatusCode);
322         
323                         // Verify that the number of resources matched by the search
324                         // is identical to the expected result
325                         long NUM_MATCHES_EXPECTED = numKeywordRetrievableResources;
326                         long numMatched = getNumMatched(res, NUM_MATCHES_EXPECTED, testName);
327                         Assert.assertEquals(numMatched, NUM_MATCHES_EXPECTED);
328                 } finally {
329                         res.close();
330                 }
331
332                 // Search using a single term
333
334                 // Send the search request and receive a response
335                 res = doSearch(TWO_MORE_KEYWORDS.get(0));
336                 try {
337                         int statusCode = res.getStatus();
338         
339                         // Check the status code of the response: does it match
340                         // the expected response(s)?
341                         if (logger.isDebugEnabled()) {
342                                 logger.debug(testName + ": status = " + statusCode);
343                         }
344                         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
345                                         invalidStatusCodeMessage(testRequestType, statusCode));
346                         Assert.assertEquals(statusCode, testExpectedStatusCode);
347         
348                         // Verify that the number of resources matched by the search
349                         // is identical to the expected result
350                         long NUM_MATCHES_EXPECTED = numKeywordRetrievableResources;
351                         long numMatched = getNumMatched(res, NUM_MATCHES_EXPECTED, testName);
352                         Assert.assertEquals(numMatched, NUM_MATCHES_EXPECTED);
353                 } finally {
354                         res.close();
355                 }
356
357         }
358
359         // @Test(dataProvider="testName",
360         // dataProviderClass=AbstractServiceTestImpl.class)
361         // public void searchWithOneKeywordInRepeatableScalarField(String testName)
362         // throws Exception {
363         // BriefDescriptionList descriptionList = new BriefDescriptionList();
364         // List<String> descriptions = descriptionList.getBriefDescription();
365         // if (TWO_KEYWORDS.size() >= 2) {
366         // descriptions.add(TWO_KEYWORDS.get(0));
367         // descriptions.add(TWO_KEYWORDS.get(1));
368         // }
369         // }
370         @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class, groups = { "utf8" })
371         public void searchWithUTF8Keyword(String testName) throws Exception {
372                 // Create one or more keyword retrievable resources, each containing
373                 // two specified keywords.
374                 long numKeywordRetrievableResources = 2;
375                 if (logger.isDebugEnabled()) {
376                         logger.debug("Creating " + numKeywordRetrievableResources
377                                         + " keyword-retrievable resources ...");
378                 }
379                 createCollectionObjects(numKeywordRetrievableResources, UTF8_KEYWORD);
380
381                 // Set the expected status code and group of valid status codes
382                 testSetup(STATUS_OK, ServiceRequestType.SEARCH);
383
384                 // Send the search request and receive a response
385                 Response res = doSearch(UTF8_KEYWORD);
386                 try {
387                         int statusCode = res.getStatus();
388         
389                         // Check the status code of the response: does it match
390                         // the expected response(s)?
391                         if (logger.isDebugEnabled()) {
392                                 logger.debug(testName + ": status = " + statusCode);
393                         }
394                         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
395                                         invalidStatusCodeMessage(testRequestType, statusCode));
396                         Assert.assertEquals(statusCode, testExpectedStatusCode);
397         
398                         // Verify that the number of resources matched by the search
399                         // is identical to the expected result
400                         long NUM_MATCHES_EXPECTED = numKeywordRetrievableResources;
401                         long numMatched = getNumMatched(res, NUM_MATCHES_EXPECTED, testName);
402                         Assert.assertEquals(numMatched, NUM_MATCHES_EXPECTED);
403                 } finally {
404                         res.close();
405                 }
406         }
407
408         // Failure outcomes
409         // FIXME: Rename to searchWithNonExistentKeyword
410         @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
411         public void keywordSearchNonExistentKeyword(String testName)
412                         throws Exception {
413                 // Set the expected status code and group of valid status codes
414                 testSetup(STATUS_OK, ServiceRequestType.SEARCH);
415
416                 // Send the search request and receive a response
417                 Response res = doSearch(NON_EXISTENT_KEYWORD);
418                 try {
419                         int statusCode = res.getStatus();
420
421                         // Check the status code of the response: does it match
422                         // the expected response(s)?
423                         if (logger.isDebugEnabled()) {
424                                 logger.debug(testName + ": status = " + statusCode);
425                         }
426                         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
427                                         invalidStatusCodeMessage(testRequestType, statusCode));
428                         Assert.assertEquals(statusCode, testExpectedStatusCode);
429         
430                         // Verify that the number of resources matched by the search
431                         // is identical to the expected result
432                         long NUM_MATCHES_EXPECTED = 0;
433                         long numMatched = getNumMatched(res, NUM_MATCHES_EXPECTED, testName);
434                         Assert.assertEquals(numMatched, NUM_MATCHES_EXPECTED);
435                 } finally {
436                         res.close();
437                 }
438         }
439
440         // ---------------------------------------------------------------
441         // Cleanup of resources created during testing
442         // ---------------------------------------------------------------
443         /**
444          * Deletes all resources created by setup and tests, after all tests have
445          * been run.
446          * 
447          * This cleanup method will always be run, even if one or more tests fail.
448          * For this reason, it attempts to remove all resources created at any point
449          * during testing, even if some of those resources may be expected to be
450          * deleted by certain tests.
451          * @throws Exception 
452          */
453         @AfterClass(alwaysRun = true)
454         public void cleanUp() throws Exception {
455                 String noTest = System.getProperty("noTestCleanup");
456                 if (Boolean.TRUE.toString().equalsIgnoreCase(noTest)) {
457                         if (logger.isDebugEnabled()) {
458                                 logger.debug("Skipping Cleanup phase ...");
459                         }
460                         return;
461                 }
462                 if (logger.isDebugEnabled()) {
463                         logger.debug("Cleaning up temporary resources created for testing ...");
464                 }
465                 CollectionObjectClient collectionObjectClient = new CollectionObjectClient();
466                 for (String resourceId : allResourceIdsCreated) {
467                         // Note: Any non-success responses are ignored and not reported.
468                         collectionObjectClient.delete(resourceId).close();
469                 }
470         }
471
472         // ---------------------------------------------------------------
473         // Utility methods used by tests above
474         // ---------------------------------------------------------------
475         private void createCollectionObjects(long numToCreate, String keyword) throws Exception {
476                 List keywords = new ArrayList<String>();
477                 keywords.add(keyword);
478                 boolean keywordsInSameField = true;
479                 createCollectionObjects(numToCreate, keywords, keywordsInSameField);
480         }
481
482         private void createCollectionObjects(long numToCreate,
483                         List<String> keywords, boolean keywordsInSameField) throws Exception {
484                 testSetup(STATUS_CREATED, ServiceRequestType.CREATE);
485                 CollectionObjectClient client = new CollectionObjectClient();
486                 for (long i = 0; i < numToCreate; i++) {
487                         PoxPayloadOut multipart = createCollectionObjectInstance(i,
488                                         keywords, keywordsInSameField);
489                         Response res = client.create(multipart);
490                         try {
491                                 int statusCode = res.getStatus();
492                                 Assert.assertEquals(statusCode, testExpectedStatusCode);
493                                 String id = extractId(res);
494                                 allResourceIdsCreated.add(id);
495                                 if (logger.isDebugEnabled()) {
496                                         logger.debug("Created new resource [" + i + "] with ID "
497                                                         + id);
498                                 }
499                         } finally {
500                                 res.close();
501                         }
502                 }
503         }
504
505         private PoxPayloadOut createCollectionObjectInstance(long i,
506                         List<String> keywords, boolean keywordsInSameField) throws Exception {
507                 CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
508                 collectionObject.setObjectNumber(createIdentifier());
509                 if (keywordsInSameField) {
510                         collectionObject.setDistinguishingFeatures(listToString(keywords,
511                                         KEYWORD_SEPARATOR));
512                 } else {
513                         if (keywords.size() == 1) {
514                                 collectionObject.setDistinguishingFeatures(keywords.get(0));
515                         } else if (keywords.size() == 2) {
516                                 collectionObject.setDistinguishingFeatures(keywords.get(0));
517                                 collectionObject.setPhysicalDescription(keywords.get(1));
518                         } else {
519                                 Assert.fail("List of keywords must have exactly one or two members.");
520                         }
521                 }
522                 PoxPayloadOut multipart = new PoxPayloadOut(
523                                 CollectionObjectClient.SERVICE_PAYLOAD_NAME);
524                 PayloadOutputPart commonPart = multipart.addPart(collectionObject, MediaType.APPLICATION_XML_TYPE);
525                 commonPart.setLabel(new CollectionObjectClient().getCommonPartName());
526                 
527                 return multipart;
528         }
529
530         private static String listToString(List<String> list, String separator) {
531                 StringBuffer sb = new StringBuffer();
532                 if (list.size() > 0) {
533                         sb.append(list.get(0));
534                         for (int i = 1; i < list.size(); i++) {
535                                 sb.append(separator);
536                                 sb.append(list.get(i));
537                         }
538                 }
539                 return sb.toString();
540         }
541
542         private Response doSearch(List<String> keywords) throws Exception {
543                 String searchParamValue = listToString(keywords, KEYWORD_SEPARATOR);
544                 return doSearch(searchParamValue);
545         }
546
547         private Response doAdvancedSearch(
548                         String propertyName, String propertyValue, String operator) throws Exception {
549                 if (logger.isDebugEnabled()) {
550                         logger.debug("Searching on property: " + propertyName + "="
551                                         + "'" + propertyValue + "'");
552                 }
553                 String whereClause = propertyName + operator +
554                         "'" + propertyValue + "'";
555                 CollectionObjectClient client = new CollectionObjectClient();
556                 Response res = client.advancedSearchIncludeDeleted(whereClause, false); // NOT_INCLUDING_DELETED_RESOURCES
557         
558                 return res;
559         }
560
561         private Response doSearch(String keyword) throws Exception {
562                 String searchParamValue = keyword;
563                 if (logger.isDebugEnabled()) {
564                         logger.debug("Searching on keyword(s): " + searchParamValue
565                                         + " ...");
566                 }
567                 CollectionObjectClient client = new CollectionObjectClient();
568                 final boolean NOT_INCLUDING_DELETED_RESOURCES = false;
569                 Response res = client.keywordSearchIncludeDeleted(searchParamValue,
570                                                 NOT_INCLUDING_DELETED_RESOURCES);
571                 return res;
572         }
573
574         private long getNumMatched(Response res, long numExpectedMatches, String testName) {
575                 AbstractCommonList list = (AbstractCommonList) res.readEntity(AbstractCommonList.class);
576                 long numMatched = list.getTotalItems();
577                 if (logger.isDebugEnabled()) {
578                         logger.debug("Keyword search matched " + numMatched
579                                         + " resources, expected to match " + numExpectedMatches);
580                 }
581
582                 // Optionally output additional data about list members for debugging.
583                 if (logger.isTraceEnabled()) {
584                         AbstractCommonListUtils.ListItemsInAbstractCommonList(list, logger,
585                                         testName);
586                 }
587
588                 return numMatched;
589         }
590
591         private void itemizeListItems(AbstractCommonList list) {
592                 List<AbstractCommonList.ListItem> items = list.getListItem();
593                 int i = 0;
594                 for (AbstractCommonList.ListItem item : items) {
595                         logger.debug("list-item["
596                                         + i
597                                         + "] title="
598                                         + AbstractCommonListUtils.ListItemGetElementValue(item,
599                                                         "title"));
600                         logger.debug("list-item["
601                                         + i
602                                         + "] URI="
603                                         + AbstractCommonListUtils.ListItemGetElementValue(item,
604                                                         "uri"));
605                         i++;
606                 }
607         }
608
609         public static String getSystemTimeIdentifier() {
610                 return Long.toString(System.currentTimeMillis());
611         }
612 }