]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
a673be7c3a6e6344c6c4233f5650a16e3623172c
[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
98                                                                                                         // http://issues.collectionspace.org/browse/CSPACE-3498
99         }
100
101         @Override
102         protected String getServicePathComponent() {
103                 // TODO Auto-generated method stub
104                 throw new UnsupportedOperationException(); // FIXME: REM - See
105                                                                                                         // http://issues.collectionspace.org/browse/CSPACE-3498
106         }
107
108         // /* (non-Javadoc)
109         // * @see
110         // org.collectionspace.services.client.test.BaseServiceTest#getServicePathComponent()
111         // */
112         // @Override
113         // protected String getServicePathComponent() {
114         // return new CollectionObjectClient().getServicePathComponent(); //FIXME:
115         // REM = Remove all refs to this method.
116         // }
117
118         /*
119          * (non-Javadoc)
120          * 
121          * @see
122          * org.collectionspace.services.client.test.BaseServiceTest#getClientInstance
123          * ()
124          */
125         @Override
126         protected CollectionSpaceClient getClientInstance() {
127                 return new CollectionObjectClient();
128         }
129
130         @Override
131         protected CollectionSpaceClient getClientInstance(String clientPropertiesFilename) {
132                 return new CollectionObjectClient(clientPropertiesFilename);
133         }
134         
135         /**
136          * Creates one or more resources containing a "noise" keyword, which should
137          * NOT be retrieved by keyword searches.
138          * 
139          * This also helps ensure that searches will not fail, due to a
140          * database-specific constraint or otherwise, if the number of records
141          * containing a particular keyword represent too high a proportion of the
142          * total number of records.
143          */
144         @BeforeClass(alwaysRun = true)
145         public void setup() {
146                 if (logger.isDebugEnabled()) {
147                         logger.debug("Creating " + numNoiseWordResources
148                                         + " 'noise word' resources ...");
149                 }
150                 createCollectionObjects(numNoiseWordResources, NOISE_WORD);
151         }
152
153         // ---------------------------------------------------------------
154         // Search tests
155         // ---------------------------------------------------------------
156         // Success outcomes
157
158         @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class, groups = { "advancedSearch" })
159         public void advancedSearch(String testName) throws Exception {
160                 // Create one or more keyword retrievable resources, each containing
161                 // a specified keyword.
162                 String theKeyword = KEYWORD + "COW";
163                 long numKeywordRetrievableResources = 1;
164                 createCollectionObjects(numKeywordRetrievableResources, theKeyword);
165
166                 // Set the expected status code and group of valid status codes
167                 testSetup(STATUS_OK, ServiceRequestType.SEARCH);
168
169                 // Send the search request and receive a response
170                 String propertyName = CollectionObjectClient.SERVICE_COMMON_PART_NAME + ":" +
171                         CollectionObjectJAXBSchema.DISTINGUISHING_FEATURES;
172                 String propertyValue = theKeyword;
173                 Response res = doAdvancedSearch(propertyName, propertyValue, "=");
174                 try {
175                         int statusCode = res.getStatus();
176         
177                         // Check the status code of the response: does it match
178                         // the expected response(s)?
179                         if (logger.isDebugEnabled()) {
180                                 logger.debug(testName + ": status = " + statusCode);
181                         }
182                         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
183                                         invalidStatusCodeMessage(testRequestType, statusCode));
184                         Assert.assertEquals(statusCode, testExpectedStatusCode);
185         
186                         // Verify that the number of resources matched by the search
187                         // is identical to the expected result
188                         long NUM_MATCHES_EXPECTED = numKeywordRetrievableResources;
189                         long numMatched = getNumMatched(res, NUM_MATCHES_EXPECTED, testName);
190                         Assert.assertEquals(numMatched, NUM_MATCHES_EXPECTED);
191                 } finally {
192                         res.close();
193                 }
194         }
195
196         @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class, groups = { "oneKeyword" })
197         public void searchWithOneKeyword(String testName) throws Exception {
198                 // Create one or more keyword retrievable resources, each containing
199                 // a specified keyword.
200                 long numKeywordRetrievableResources = (long) (numNoiseWordResources * pctNonNoiseWordResources);
201                 if (logger.isDebugEnabled()) {
202                         logger.debug("Creating " + numKeywordRetrievableResources
203                                         + " keyword-retrievable resources ...");
204                 }
205                 createCollectionObjects(numKeywordRetrievableResources, KEYWORD);
206
207                 // Set the expected status code and group of valid status codes
208                 testSetup(STATUS_OK, ServiceRequestType.SEARCH);
209
210                 // Send the search request and receive a response
211                 Response res = doSearch(KEYWORD);
212                 try {
213                         int statusCode = res.getStatus();
214         
215                         // Check the status code of the response: does it match
216                         // the expected response(s)?
217                         if (logger.isDebugEnabled()) {
218                                 logger.debug(testName + ": status = " + statusCode);
219                         }
220                         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
221                                         invalidStatusCodeMessage(testRequestType, statusCode));
222                         Assert.assertEquals(statusCode, testExpectedStatusCode);
223         
224                         // Verify that the number of resources matched by the search
225                         // is identical to the expected result
226                         long NUM_MATCHES_EXPECTED = numKeywordRetrievableResources;
227                         long numMatched = getNumMatched(res, NUM_MATCHES_EXPECTED, testName);
228                         Assert.assertEquals(numMatched, NUM_MATCHES_EXPECTED);
229                 } finally {
230                         res.close();
231                 }
232         }
233
234         @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
235         public void searchWithTwoKeywordsInSameField(String testName)
236                         throws Exception {
237                 // Create one or more keyword retrievable resources, each containing
238                 // two specified keywords.
239                 long numKeywordRetrievableResources = (long) (numNoiseWordResources * pctNonNoiseWordResources);
240                 if (logger.isDebugEnabled()) {
241                         logger.debug("Creating " + numKeywordRetrievableResources
242                                         + " keyword-retrievable resources ...");
243                 }
244                 boolean keywordsInSameField = true;
245                 createCollectionObjects(numKeywordRetrievableResources, TWO_KEYWORDS,
246                                 keywordsInSameField);
247
248                 // Set the expected status code and group of valid status codes
249                 testSetup(STATUS_OK, ServiceRequestType.SEARCH);
250
251                 // Search using both terms
252
253                 // Send the search request and receive a response
254                 Response res = doSearch(TWO_KEYWORDS);
255                 try {
256                         int statusCode = res.getStatus();
257         
258                         // Check the status code of the response: does it match
259                         // the expected response(s)?
260                         if (logger.isDebugEnabled()) {
261                                 logger.debug(testName + ": status = " + statusCode);
262                         }
263                         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
264                                         invalidStatusCodeMessage(testRequestType, statusCode));
265                         Assert.assertEquals(statusCode, testExpectedStatusCode);
266         
267                         // Verify that the number of resources matched by the search
268                         // is identical to the expected result
269                         long NUM_MATCHES_EXPECTED = numKeywordRetrievableResources;
270                         long numMatched = getNumMatched(res, NUM_MATCHES_EXPECTED, testName);
271                         Assert.assertEquals(numMatched, NUM_MATCHES_EXPECTED);
272                 } finally {
273                         res.close();
274                 }
275
276                 // Search using a single term
277
278                 // Send the search request and receive a response
279                 res = doSearch(TWO_KEYWORDS.get(0));
280                 try {
281                         int statusCode = res.getStatus();
282         
283                         // Check the status code of the response: does it match
284                         // the expected response(s)?
285                         if (logger.isDebugEnabled()) {
286                                 logger.debug(testName + ": status = " + statusCode);
287                         }
288                         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
289                                         invalidStatusCodeMessage(testRequestType, statusCode));
290                         Assert.assertEquals(statusCode, testExpectedStatusCode);
291         
292                         // Verify that the number of resources matched by the search
293                         // is identical to the expected result
294                         long NUM_MATCHES_EXPECTED = numKeywordRetrievableResources;
295                         long numMatched = getNumMatched(res, NUM_MATCHES_EXPECTED, testName);
296                         Assert.assertEquals(numMatched, NUM_MATCHES_EXPECTED);
297                 } finally {
298                         res.close();
299                 }
300         }
301
302         @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
303         public void searchWithTwoKeywordsAcrossTwoFields(String testName)
304                         throws Exception {
305                 // Create one or more keyword retrievable resources, each containing
306                 // two specified keywords.
307                 long numKeywordRetrievableResources = 5;
308                 if (logger.isDebugEnabled()) {
309                         logger.debug("Creating " + numKeywordRetrievableResources
310                                         + " keyword-retrievable resources ...");
311                 }
312                 boolean keywordsInSameField = false;
313                 createCollectionObjects(numKeywordRetrievableResources,
314                                 TWO_MORE_KEYWORDS, keywordsInSameField);
315
316                 // Set the expected status code and group of valid status codes
317                 testSetup(STATUS_OK, ServiceRequestType.SEARCH);
318
319                 // Search using both terms
320
321                 // Send the search request and receive a response
322                 Response res = doSearch(TWO_MORE_KEYWORDS);
323                 try {
324                         int statusCode = res.getStatus();
325         
326                         // Check the status code of the response: does it match
327                         // the expected response(s)?
328                         if (logger.isDebugEnabled()) {
329                                 logger.debug(testName + ": status = " + statusCode);
330                         }
331                         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
332                                         invalidStatusCodeMessage(testRequestType, statusCode));
333                         Assert.assertEquals(statusCode, testExpectedStatusCode);
334         
335                         // Verify that the number of resources matched by the search
336                         // is identical to the expected result
337                         long NUM_MATCHES_EXPECTED = numKeywordRetrievableResources;
338                         long numMatched = getNumMatched(res, NUM_MATCHES_EXPECTED, testName);
339                         Assert.assertEquals(numMatched, NUM_MATCHES_EXPECTED);
340                 } finally {
341                         res.close();
342                 }
343
344                 // Search using a single term
345
346                 // Send the search request and receive a response
347                 res = doSearch(TWO_MORE_KEYWORDS.get(0));
348                 try {
349                         int statusCode = res.getStatus();
350         
351                         // Check the status code of the response: does it match
352                         // the expected response(s)?
353                         if (logger.isDebugEnabled()) {
354                                 logger.debug(testName + ": status = " + statusCode);
355                         }
356                         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
357                                         invalidStatusCodeMessage(testRequestType, statusCode));
358                         Assert.assertEquals(statusCode, testExpectedStatusCode);
359         
360                         // Verify that the number of resources matched by the search
361                         // is identical to the expected result
362                         long NUM_MATCHES_EXPECTED = numKeywordRetrievableResources;
363                         long numMatched = getNumMatched(res, NUM_MATCHES_EXPECTED, testName);
364                         Assert.assertEquals(numMatched, NUM_MATCHES_EXPECTED);
365                 } finally {
366                         res.close();
367                 }
368
369         }
370
371         // @Test(dataProvider="testName",
372         // dataProviderClass=AbstractServiceTestImpl.class)
373         // public void searchWithOneKeywordInRepeatableScalarField(String testName)
374         // throws Exception {
375         // BriefDescriptionList descriptionList = new BriefDescriptionList();
376         // List<String> descriptions = descriptionList.getBriefDescription();
377         // if (TWO_KEYWORDS.size() >= 2) {
378         // descriptions.add(TWO_KEYWORDS.get(0));
379         // descriptions.add(TWO_KEYWORDS.get(1));
380         // }
381         // }
382         @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class, groups = { "utf8" })
383         public void searchWithUTF8Keyword(String testName) {
384                 // Create one or more keyword retrievable resources, each containing
385                 // two specified keywords.
386                 long numKeywordRetrievableResources = 2;
387                 if (logger.isDebugEnabled()) {
388                         logger.debug("Creating " + numKeywordRetrievableResources
389                                         + " keyword-retrievable resources ...");
390                 }
391                 createCollectionObjects(numKeywordRetrievableResources, UTF8_KEYWORD);
392
393                 // Set the expected status code and group of valid status codes
394                 testSetup(STATUS_OK, ServiceRequestType.SEARCH);
395
396                 // Send the search request and receive a response
397                 Response res = doSearch(UTF8_KEYWORD);
398                 try {
399                         int statusCode = res.getStatus();
400         
401                         // Check the status code of the response: does it match
402                         // the expected response(s)?
403                         if (logger.isDebugEnabled()) {
404                                 logger.debug(testName + ": status = " + statusCode);
405                         }
406                         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
407                                         invalidStatusCodeMessage(testRequestType, statusCode));
408                         Assert.assertEquals(statusCode, testExpectedStatusCode);
409         
410                         // Verify that the number of resources matched by the search
411                         // is identical to the expected result
412                         long NUM_MATCHES_EXPECTED = numKeywordRetrievableResources;
413                         long numMatched = getNumMatched(res, NUM_MATCHES_EXPECTED, testName);
414                         Assert.assertEquals(numMatched, NUM_MATCHES_EXPECTED);
415                 } finally {
416                         res.close();
417                 }
418         }
419
420         // Failure outcomes
421         // FIXME: Rename to searchWithNonExistentKeyword
422         @Test(dataProvider = "testName", dataProviderClass = AbstractServiceTestImpl.class)
423         public void keywordSearchNonExistentKeyword(String testName)
424                         throws Exception {
425                 // Set the expected status code and group of valid status codes
426                 testSetup(STATUS_OK, ServiceRequestType.SEARCH);
427
428                 // Send the search request and receive a response
429                 Response res = doSearch(NON_EXISTENT_KEYWORD);
430                 try {
431                         int statusCode = res.getStatus();
432
433                         // Check the status code of the response: does it match
434                         // the expected response(s)?
435                         if (logger.isDebugEnabled()) {
436                                 logger.debug(testName + ": status = " + statusCode);
437                         }
438                         Assert.assertTrue(testRequestType.isValidStatusCode(statusCode),
439                                         invalidStatusCodeMessage(testRequestType, statusCode));
440                         Assert.assertEquals(statusCode, testExpectedStatusCode);
441         
442                         // Verify that the number of resources matched by the search
443                         // is identical to the expected result
444                         long NUM_MATCHES_EXPECTED = 0;
445                         long numMatched = getNumMatched(res, NUM_MATCHES_EXPECTED, testName);
446                         Assert.assertEquals(numMatched, NUM_MATCHES_EXPECTED);
447                 } finally {
448                         res.close();
449                 }
450         }
451
452         // ---------------------------------------------------------------
453         // Cleanup of resources created during testing
454         // ---------------------------------------------------------------
455         /**
456          * Deletes all resources created by setup and tests, after all tests have
457          * been run.
458          * 
459          * This cleanup method will always be run, even if one or more tests fail.
460          * For this reason, it attempts to remove all resources created at any point
461          * during testing, even if some of those resources may be expected to be
462          * deleted by certain tests.
463          */
464         @AfterClass(alwaysRun = true)
465         public void cleanUp() {
466                 String noTest = System.getProperty("noTestCleanup");
467                 if (Boolean.TRUE.toString().equalsIgnoreCase(noTest)) {
468                         if (logger.isDebugEnabled()) {
469                                 logger.debug("Skipping Cleanup phase ...");
470                         }
471                         return;
472                 }
473                 if (logger.isDebugEnabled()) {
474                         logger.debug("Cleaning up temporary resources created for testing ...");
475                 }
476                 CollectionObjectClient collectionObjectClient = new CollectionObjectClient();
477                 for (String resourceId : allResourceIdsCreated) {
478                         // Note: Any non-success responses are ignored and not reported.
479                         collectionObjectClient.delete(resourceId).close();
480                 }
481         }
482
483         // ---------------------------------------------------------------
484         // Utility methods used by tests above
485         // ---------------------------------------------------------------
486         private void createCollectionObjects(long numToCreate, String keyword) {
487                 List keywords = new ArrayList<String>();
488                 keywords.add(keyword);
489                 boolean keywordsInSameField = true;
490                 createCollectionObjects(numToCreate, keywords, keywordsInSameField);
491         }
492
493         private void createCollectionObjects(long numToCreate,
494                         List<String> keywords, boolean keywordsInSameField) {
495                 testSetup(STATUS_CREATED, ServiceRequestType.CREATE);
496                 CollectionObjectClient client = new CollectionObjectClient();
497                 for (long i = 0; i < numToCreate; i++) {
498                         PoxPayloadOut multipart = createCollectionObjectInstance(i,
499                                         keywords, keywordsInSameField);
500                         Response res = client.create(multipart);
501                         try {
502                                 int statusCode = res.getStatus();
503                                 Assert.assertEquals(statusCode, testExpectedStatusCode);
504                                 String id = extractId(res);
505                                 allResourceIdsCreated.add(id);
506                                 if (logger.isDebugEnabled()) {
507                                         logger.debug("Created new resource [" + i + "] with ID "
508                                                         + id);
509                                 }
510                         } finally {
511                                 res.close();
512                         }
513                 }
514         }
515
516         private PoxPayloadOut createCollectionObjectInstance(long i,
517                         List<String> keywords, boolean keywordsInSameField) {
518                 CollectionobjectsCommon collectionObject = new CollectionobjectsCommon();
519                 collectionObject.setObjectNumber(createIdentifier());
520                 if (keywordsInSameField) {
521                         collectionObject.setDistinguishingFeatures(listToString(keywords,
522                                         KEYWORD_SEPARATOR));
523                 } else {
524                         if (keywords.size() == 1) {
525                                 collectionObject.setDistinguishingFeatures(keywords.get(0));
526                         } else if (keywords.size() == 2) {
527                                 collectionObject.setDistinguishingFeatures(keywords.get(0));
528                                 collectionObject.setPhysicalDescription(keywords.get(1));
529                         } else {
530                                 Assert.fail("List of keywords must have exactly one or two members.");
531                         }
532                 }
533                 PoxPayloadOut multipart = new PoxPayloadOut(
534                                 CollectionObjectClient.SERVICE_PAYLOAD_NAME);
535                 PayloadOutputPart commonPart = multipart.addPart(collectionObject, MediaType.APPLICATION_XML_TYPE);
536                 commonPart.setLabel(new CollectionObjectClient().getCommonPartName());
537                 
538                 return multipart;
539         }
540
541         private static String listToString(List<String> list, String separator) {
542                 StringBuffer sb = new StringBuffer();
543                 if (list.size() > 0) {
544                         sb.append(list.get(0));
545                         for (int i = 1; i < list.size(); i++) {
546                                 sb.append(separator);
547                                 sb.append(list.get(i));
548                         }
549                 }
550                 return sb.toString();
551         }
552
553         private Response doSearch(List<String> keywords) {
554                 String searchParamValue = listToString(keywords, KEYWORD_SEPARATOR);
555                 return doSearch(searchParamValue);
556         }
557
558         private Response doAdvancedSearch(
559                         String propertyName, String propertyValue, String operator) {
560                 if (logger.isDebugEnabled()) {
561                         logger.debug("Searching on property: " + propertyName + "="
562                                         + "'" + propertyValue + "'");
563                 }
564                 String whereClause = propertyName + operator +
565                         "'" + propertyValue + "'";
566                 CollectionObjectClient client = new CollectionObjectClient();
567                 Response res = client.advancedSearchIncludeDeleted(whereClause, false); // NOT_INCLUDING_DELETED_RESOURCES
568         
569                 return res;
570         }
571
572         private Response doSearch(String keyword) {
573                 String searchParamValue = keyword;
574                 if (logger.isDebugEnabled()) {
575                         logger.debug("Searching on keyword(s): " + searchParamValue
576                                         + " ...");
577                 }
578                 CollectionObjectClient client = new CollectionObjectClient();
579                 final boolean NOT_INCLUDING_DELETED_RESOURCES = false;
580                 Response res = client.keywordSearchIncludeDeleted(searchParamValue,
581                                                 NOT_INCLUDING_DELETED_RESOURCES);
582                 return res;
583         }
584
585         private long getNumMatched(Response res, long numExpectedMatches, String testName) {
586                 AbstractCommonList list = (AbstractCommonList) res.readEntity(AbstractCommonList.class);
587                 long numMatched = list.getTotalItems();
588                 if (logger.isDebugEnabled()) {
589                         logger.debug("Keyword search matched " + numMatched
590                                         + " resources, expected to match " + numExpectedMatches);
591                 }
592
593                 // Optionally output additional data about list members for debugging.
594                 if (logger.isTraceEnabled()) {
595                         AbstractCommonListUtils.ListItemsInAbstractCommonList(list, logger,
596                                         testName);
597                 }
598
599                 return numMatched;
600         }
601
602         private void itemizeListItems(AbstractCommonList list) {
603                 List<AbstractCommonList.ListItem> items = list.getListItem();
604                 int i = 0;
605                 for (AbstractCommonList.ListItem item : items) {
606                         logger.debug("list-item["
607                                         + i
608                                         + "] title="
609                                         + AbstractCommonListUtils.ListItemGetElementValue(item,
610                                                         "title"));
611                         logger.debug("list-item["
612                                         + i
613                                         + "] URI="
614                                         + AbstractCommonListUtils.ListItemGetElementValue(item,
615                                                         "uri"));
616                         i++;
617                 }
618         }
619
620         public static String getSystemTimeIdentifier() {
621                 return Long.toString(System.currentTimeMillis());
622         }
623 }