]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
e5a5f0c429308186031b5beb0649878b037d92e3
[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 (c)) 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.io.UnsupportedEncodingException;
26 import java.net.URLEncoder;
27 import java.util.ArrayList;
28 import java.util.HashMap;
29 import java.util.List;
30 import java.util.Map;
31 import javax.ws.rs.core.Response;
32
33 import org.collectionspace.services.PersonJAXBSchema;
34 import org.collectionspace.services.client.CollectionSpaceClient;
35 import org.collectionspace.services.client.PersonAuthorityClient;
36 import org.collectionspace.services.client.PersonAuthorityClientUtils;
37 import org.collectionspace.services.client.PoxPayloadOut;
38 import org.collectionspace.services.jaxb.AbstractCommonList;
39 import org.collectionspace.services.person.PersonTermGroup;
40 import org.jboss.resteasy.client.ClientResponse;
41 import org.slf4j.Logger;
42 import org.slf4j.LoggerFactory;
43 import org.testng.Assert;
44 import org.testng.annotations.AfterClass;
45 import org.testng.annotations.BeforeClass;
46 import org.testng.annotations.Test;
47
48 /**
49  * PersonAuthoritySearchTest, carries out search (e.g. partial
50  * term matching) tests against a deployed and running PersonAuthority Service.
51  *
52  * $LastChangedRevision: 753 $
53  * $LastChangedDate: 2009-09-23 11:03:36 -0700 (Wed, 23 Sep 2009) $
54  */
55 public class PersonAuthoritySearchTest extends BaseServiceTest<AbstractCommonList> {
56
57     private final String CLASS_NAME = PersonAuthoritySearchTest.class.getName();
58     private final Logger logger = LoggerFactory.getLogger(CLASS_NAME);
59     
60         @Override
61         public String getServicePathComponent() {
62                 return PersonAuthorityClient.SERVICE_PATH_COMPONENT;
63         }
64
65         @Override
66         protected String getServiceName() {
67                 return PersonAuthorityClient.SERVICE_NAME;
68         }
69     
70     final String UTF8_CHARSET_NAME = "UTF-8";
71     
72     // Test name for partial term matching: Lech Wałęsa
73     //
74     // For details regarding the łę characters in the last name, see:
75     // http://en.wikipedia.org/wiki/L_with_stroke
76     // http://en.wikipedia.org/wiki/%C4%98
77     //
78     // Forename
79     final String TEST_PARTIAL_TERM_FORE_NAME = "Lech";
80     //
81     // Surname (contains single quote character)
82     final String TEST_PARTIAL_TERM_SUR_NAME_QUOTE = "O'Hara";
83     //
84     // Surname (contains two non-USASCII range Unicode UTF-8 characters)
85     final String TEST_PARTIAL_TERM_SUR_NAME_UNICODE = "Wałęsa";
86         // Wrong: "Wa" + "\u0142" + "\u0119" + "sa";
87         // Should also work: "Wa" + '\u0142' + '\u0119' + "sa";
88         // Should also work: "Wa\u0142\u0119sa";
89     //
90     //
91     // Displayname
92     final String TEST_PARTIAL_TERM_DISPLAY_NAME_UNICODE =
93             TEST_PARTIAL_TERM_FORE_NAME + " " + TEST_PARTIAL_TERM_SUR_NAME_UNICODE;
94     //
95     // Displayname
96     final String TEST_PARTIAL_TERM_DISPLAY_NAME_QUOTE =
97             TEST_PARTIAL_TERM_FORE_NAME + " " + TEST_PARTIAL_TERM_SUR_NAME_QUOTE;
98     //
99     // shortId
100     final String TEST_SHORT_ID_UNICODE = "lechWalesa";
101     //
102     // shortId
103     final String TEST_SHORT_ID_QUOTE = "lechOHara";
104     
105     final String TEST_KWD_BIRTH_PLACE = "Popowo, Poland";
106
107     final String TEST_KWD_UTF8_STYLE = "Appliqu"+'\u00e8'+"d Arts";
108     
109     final String TEST_KWD_BIO_NOTE_NO_QUOTES = 
110         "This is a silly bionote with no so-called quotes.";
111     
112     final String TEST_KWD_BIO_NOTE_DBL_QUOTES = 
113         "This is a silly \"bionote\" for testing so called quote_handling";
114
115     final String TEST_KWD_NO_MATCH = "Foobar";
116
117     // Non-existent partial term name (first letters of each of the words
118     // in a pangram for the English alphabet).
119     private static final String TEST_PARTIAL_TERM_NON_EXISTENT = "jlmbsoq";
120
121     /** The known resource id. */
122     private String knownResourceId = null;
123     
124     /** The known resource ref name. */
125     //private String knownResourceRefName = null;
126     
127     /** The known item resource id. */
128     private String knownItemResourceId = null;
129
130     // The resource ID of an item resource used for partial term matching tests.
131     private String knownItemPartialTermResourceId = null;
132
133     private List<String> allResourceIdsCreated = new ArrayList<String>();
134     
135     /** The all item resource ids created. */
136     private Map<String, String> allItemResourceIdsCreated =
137         new HashMap<String, String>();
138
139     // The number of matches expected on each partial term.
140     final int NUM_MATCHES_EXPECTED_COMMON = 2;
141     final int NUM_MATCHES_EXPECTED_SPECIFIC = 1;
142
143     // The minimum number of characters that must be included
144     // a partial term, in order to permit matching to occur.
145     final int PARTIAL_TERM_MIN_LENGTH = 1;
146
147     /* (non-Javadoc)
148      * @see org.collectionspace.services.client.test.BaseServiceTest#getClientInstance()
149      */
150     @Override
151     protected CollectionSpaceClient getClientInstance() {
152         return new PersonAuthorityClient();
153     }
154     
155     /* (non-Javadoc)
156      * @see org.collectionspace.services.client.test.BaseServiceTest#getAbstractCommonList(org.jboss.resteasy.client.ClientResponse)
157      */
158     @Override
159     protected AbstractCommonList getCommonList(Response response) {
160         return response.readEntity(AbstractCommonList.class);
161     }
162
163     private String getPartialTermCommon() {
164         return TEST_PARTIAL_TERM_FORE_NAME;
165     }
166
167     private String getPartialTermUtf8() {
168         return TEST_PARTIAL_TERM_SUR_NAME_UNICODE;
169     }
170
171     private String getPartialTermQuote() {
172         return TEST_PARTIAL_TERM_SUR_NAME_QUOTE;
173     }
174
175     private String getPartialTermNonExistent() {
176         return TEST_PARTIAL_TERM_NON_EXISTENT;
177     }
178
179     private String getPartialTermMinimumLength() {
180         String partialTerm = getPartialTermCommon();
181         if (partialTerm == null || partialTerm.trim().isEmpty()) {
182             return partialTerm;
183         }
184         if (partialTerm.length() > PARTIAL_TERM_MIN_LENGTH) {
185             return partialTerm.substring(0, PARTIAL_TERM_MIN_LENGTH);
186         } else {
187           return partialTerm;
188         }
189     }
190
191     private String getKwdTerm() {
192         return TEST_KWD_BIRTH_PLACE;
193     }
194
195     private String getKwdTermUTF8() {
196         return TEST_KWD_UTF8_STYLE;
197     }
198
199     private String getKwdTermNonExistent() {
200         return TEST_KWD_NO_MATCH;
201     }
202
203     @BeforeClass
204     public void setup() {
205         try {
206             createAuthority();
207         } catch (Exception e) {
208             Assert.fail("Could not create new Authority for search tests.", e);
209         }
210         try {
211             createItemsInAuthorityForPartialTermMatch(knownResourceId, null ); //knownResourceRefName);
212         } catch (Exception e) {
213             Assert.fail("Could not create new item in Authority for search tests.", e);
214         }
215     }
216  
217     // ---------------------------------------------------------------
218     // CRUD tests : READ_LIST tests by partial term match.
219     // ---------------------------------------------------------------
220
221     // Success outcomes
222
223     /**
224      * Reads an item list by partial term.
225      */
226     @Test(dataProvider="testName", groups = {"readListByPartialTerm"})
227     public void partialTermMatch(String testName) {
228         int numMatchesFound = 0;
229         String partialTerm = getPartialTermCommon();
230         if (logger.isDebugEnabled()) {
231             logger.debug("Attempting match on partial term '" + partialTerm + "' ...");
232         }
233         numMatchesFound = readItemListWithFilters(testName, knownResourceId, partialTerm, null);
234         if (logger.isDebugEnabled()) {
235             logger.debug("Found " + numMatchesFound + " match(es), expected " +
236                 NUM_MATCHES_EXPECTED_COMMON + " match(es).");
237         }
238         Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED_COMMON);
239     }
240
241     /**
242      * Reads an item list by partial term, with a partial term that consists
243      * of an all-lowercase variation of the expected match, to test case-insensitive
244      * matching.
245      */
246     @Test(dataProvider="testName", groups = {"readListByPartialTerm"},
247                 dependsOnMethods = {"partialTermMatch"})
248     public void partialTermMatchCaseInsensitiveLowerCase(String testName) {
249         int numMatchesFound = 0;
250
251         final String partialTerm = getPartialTermCommon().toLowerCase();
252         if (logger.isDebugEnabled()) {
253             logger.debug("Attempting match on partial term '" + partialTerm + "' ...");
254         }
255         numMatchesFound =
256                 readItemListWithFilters(testName, knownResourceId, partialTerm, null);
257                 if (logger.isDebugEnabled()) {
258         logger.debug("Found " + numMatchesFound + " match(es), expected " +
259                         NUM_MATCHES_EXPECTED_COMMON + " match(es).");
260         }
261         Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED_COMMON);
262     }
263
264     /**
265      * Reads an item list by partial term, with a partial term that consists
266      * of an all-uppercase variation of the expected match, to test case-insensitive
267      * matching.
268      */
269     @Test(dataProvider="testName",
270         groups = {"readListByPartialTerm"}, dependsOnMethods = {"partialTermMatch"})
271     public void partialTermMatchCaseInsensitiveUpperCase(String testName) {
272         int numMatchesFound = 0;
273
274         final String partialTerm = getPartialTermCommon().toUpperCase();
275         if (logger.isDebugEnabled()) {
276             logger.debug("Attempting match on partial term '" + partialTerm + "' ...");
277         }
278         numMatchesFound =
279                 readItemListWithFilters(testName, knownResourceId, partialTerm, null);
280         if (logger.isDebugEnabled()) {
281             logger.debug("Found " + numMatchesFound + " match(es), expected " +
282                         NUM_MATCHES_EXPECTED_COMMON + " match(es).");
283         }
284         Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED_COMMON);
285     }
286
287     /**
288      * Reads an item list by partial term, with a partial term that is of
289      * the minimum character length that may be expected to be matched.
290      */
291     @Test(dataProvider="testName",
292         groups = {"readListByPartialTerm"}, dependsOnMethods = {"partialTermMatch"})
293     public void partialTermMatchMinimumLength(String testName) {
294         int numMatchesFound = 0;
295         String partialTerm = getPartialTermMinimumLength();
296         if (logger.isDebugEnabled()) {
297             logger.debug("Attempting match on partial term '" + partialTerm + "' ...");
298         }
299         numMatchesFound = readItemListWithFilters(testName, knownResourceId, partialTerm, null);
300         // Zero matches are expected on a non-existent term.
301         if (logger.isDebugEnabled()) {
302             logger.debug("Found " + numMatchesFound + " match(es), expected " +
303                         NUM_MATCHES_EXPECTED_COMMON + " match(es).");
304         }
305         Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED_COMMON);
306     }
307
308     /**
309      * Reads an item list by partial term, with a partial term that contains
310      * at least one Unicode UTF-8 character (outside the USASCII range).
311      */
312     @Test(dataProvider="testName",
313         groups = {"readListByPartialTerm"}, dependsOnMethods = {"partialTermMatch"})
314     public void partialTermMatchUTF8(String testName) {
315         int numMatchesFound = 0;
316         String partialTerm = getPartialTermUtf8();
317         String ptEncoded;
318         try {
319                 ptEncoded = URLEncoder.encode(partialTerm, UTF8_CHARSET_NAME);
320         }
321         catch (UnsupportedEncodingException ex) {
322           throw new RuntimeException("Broken VM does not support UTF-8");
323         }
324         if (logger.isDebugEnabled()) {
325             logger.debug("Attempting match on partial term '" + partialTerm + "', Encoded:'"+ptEncoded+"' ...");
326         }
327         numMatchesFound =
328                 readItemListWithFilters(testName, knownResourceId, partialTerm, null);
329         if (logger.isDebugEnabled()) {
330             logger.debug("Found " + numMatchesFound + " match(es), expected " +
331                 NUM_MATCHES_EXPECTED_SPECIFIC + " match(es).");
332         }
333         Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED_SPECIFIC);
334     }
335     
336     /**
337      * Reads an item list by partial term, with a partial term that contains
338      * at least one Unicode UTF-8 character (outside the USASCII range).
339      */
340     @Test(dataProvider="testName",
341         groups = {"readListByPartialTerm"}, dependsOnMethods = {"partialTermMatch"})
342     public void partialTermMatchQuote(String testName) {
343         int numMatchesFound = 0;
344         String partialTerm = getPartialTermQuote();
345         if (logger.isDebugEnabled()) {
346             logger.debug("Attempting match on partial term '" + partialTerm + "' ...");
347         }
348         numMatchesFound =
349                 readItemListWithFilters(testName, knownResourceId, partialTerm, null);
350         if (logger.isDebugEnabled()) {
351             logger.debug("Found " + numMatchesFound + " match(es), expected " +
352                 NUM_MATCHES_EXPECTED_SPECIFIC + " match(es).");
353         }
354         Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED_SPECIFIC);
355     }
356
357     /**
358      * Finds terms by keywords.
359      */
360     @Test(dataProvider="testName", groups = {"readListByKwdTerm"})
361     public void keywordTermMatch(String testName) {
362         int numMatchesFound = 0;
363         String kwdTerm = getKwdTerm();
364         if (logger.isDebugEnabled()) {
365             logger.debug("Attempting match on kwd term '" + kwdTerm + "' ...");
366         }
367         numMatchesFound = readItemListWithFilters(testName, knownResourceId, null, kwdTerm);
368         if (logger.isDebugEnabled()) {
369             logger.debug("Found " + numMatchesFound + " match(es), expected " +
370                     NUM_MATCHES_EXPECTED_COMMON + " match(es).");
371         }
372         Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED_COMMON);
373     }
374
375     /**
376      * Finds terms by keywords.
377      */
378     @Test(dataProvider="testName",
379         groups = {"readListByKwdTerm"}, dependsOnMethods = {"keywordTermMatch"})
380     public void keywordTermMatchUTF8(String testName) {
381         int numMatchesFound = 0;
382         String kwdTerm = getKwdTermUTF8();
383         if (logger.isDebugEnabled()) {
384             logger.debug("Attempting match on kwd term '" + kwdTerm + "' ...");
385         }
386         numMatchesFound = readItemListWithFilters(testName, knownResourceId, null, kwdTerm);
387         if (logger.isDebugEnabled()) {
388             logger.debug("Found " + numMatchesFound + " match(es), expected " +
389                 NUM_MATCHES_EXPECTED_COMMON + " match(es).");
390         }
391         Assert.assertEquals(numMatchesFound, NUM_MATCHES_EXPECTED_COMMON);
392     }
393
394     
395     
396     // Failure outcomes
397
398     /**
399      * Reads an item list by partial term, with a partial term that is not
400      * expected to be matched by any term in any resource.
401      */
402     @Test(dataProvider="testName",
403         groups = {"readListByPartialTerm"}, dependsOnMethods = {"partialTermMatch"})
404     public void partialTermMatchOnNonexistentTerm(String testName) {
405         int numMatchesFound = 0;
406         int ZERO_MATCHES_EXPECTED = 0;
407         String partialTerm = getPartialTermNonExistent();
408         if (logger.isDebugEnabled()) {
409             logger.debug("Attempting match on partial term '" + partialTerm + "' ...");
410         }
411         numMatchesFound = readItemListWithFilters(testName, knownResourceId, partialTerm, null);
412         // Zero matches are expected on a non-existent term.
413         if (logger.isDebugEnabled()) {
414             logger.debug("Found " + numMatchesFound + " match(es), expected " +
415                 ZERO_MATCHES_EXPECTED + " match(es).");
416         }
417         Assert.assertEquals(numMatchesFound, ZERO_MATCHES_EXPECTED);
418     }
419
420     /**
421      * Reads an item list by partial term, with a partial term that is not
422      * expected to be matched by any term in any resource.
423      */
424     @Test(dataProvider="testName", groups = {"readListByKwdTerm"},
425                 dependsOnMethods = {"keywordTermMatch"})
426     public void keywordTermMatchOnNonexistentTerm(String testName) {
427         int numMatchesFound = 0;
428         int ZERO_MATCHES_EXPECTED = 0;
429         String kwdTerm = getKwdTermNonExistent();
430         if (logger.isDebugEnabled()) {
431             logger.debug("Attempting match on kwd term '" + kwdTerm + "' ...");
432         }
433         numMatchesFound = readItemListWithFilters(testName, knownResourceId, null, kwdTerm);
434         // Zero matches are expected on a non-existent term.
435         if (logger.isDebugEnabled()) {
436             logger.debug("Found " + numMatchesFound + " match(es), expected " +
437                 ZERO_MATCHES_EXPECTED + " match(es).");
438         }
439         Assert.assertEquals(numMatchesFound, ZERO_MATCHES_EXPECTED);
440     }
441
442     /**
443      * Reads an item list by partial term or keywords, given an authority and a term.
444      * Only one of partialTerm or keywords should be specified. 
445      * If both are specified, keywords will be ignored.
446      * 
447      * @param testName Calling test name
448      * @param authorityCsid The CSID of the authority within which partial term matching
449      *     will be performed.
450      * @param partialTerm A partial term to match item resources.
451      * @param partialTerm A keyword list to match item resources.
452      * @return The number of item resources matched by the partial term.
453      */
454     private int readItemListWithFilters(String testName, 
455                 String authorityCsid, String partialTerm, String keywords) {
456
457         // Perform setup.
458         int expectedStatusCode = Response.Status.OK.getStatusCode();
459         ServiceRequestType requestType = ServiceRequestType.READ_LIST;
460         testSetup(expectedStatusCode, requestType);
461
462         // Submit the request to the service and store the response.
463         PersonAuthorityClient client = new PersonAuthorityClient();
464         ClientResponse<AbstractCommonList> res = null;
465         if (authorityCsid != null) {
466                 res = client.readItemList(authorityCsid, partialTerm, keywords);
467         } else {
468             Assert.fail("readItemListByPartialTerm passed null csid!");
469         }
470         AbstractCommonList list = null;
471         try {
472             assertStatusCode(res, testName);
473             list = res.getEntity();
474         } finally {
475                 if (res != null) {
476                 res.releaseConnection();
477             }
478         }
479
480         List<AbstractCommonList.ListItem> items = list.getListItem();
481         int nItemsReturned = items.size();
482
483         return nItemsReturned;
484     }
485     
486     // ---------------------------------------------------------------
487     // Cleanup of resources created during testing
488     // ---------------------------------------------------------------
489     
490     /**
491      * Deletes all resources created by tests, after all tests have been run.
492      *
493      * This cleanup method will always be run, even if one or more tests fail.
494      * For this reason, it attempts to remove all resources created
495      * at any point during testing, even if some of those resources
496      * may be expected to be deleted by certain tests.
497      */
498     @AfterClass(alwaysRun=true)
499     public void cleanUp() {
500         String noTest = System.getProperty("noTestCleanup");
501         if(Boolean.TRUE.toString().equalsIgnoreCase(noTest)) {
502             if (logger.isDebugEnabled()) {
503                 logger.debug("Skipping Cleanup phase ...");
504             }
505             return;
506         }
507         if (logger.isDebugEnabled()) {
508             logger.debug("Cleaning up temporary resources created for testing ...");
509         }
510         String parentResourceId;
511         String itemResourceId;
512         PersonAuthorityClient client = new PersonAuthorityClient();
513         parentResourceId = knownResourceId;
514         // Clean up item resources.
515         for (Map.Entry<String, String> entry : allItemResourceIdsCreated.entrySet()) {
516             itemResourceId = entry.getKey();
517             parentResourceId = entry.getValue();
518             // Note: Any non-success responses from the delete operation
519             // below are ignored and not reported.
520             Response res = client.deleteItem(parentResourceId, itemResourceId);
521             res.close();
522         }
523         // Clean up authority resources.
524         for (String resourceId : allResourceIdsCreated) {
525             // Note: Any non-success responses are ignored and not reported.
526             client.delete(resourceId).close();
527         }
528     }
529
530     // ---------------------------------------------------------------
531     // Utility methods used by tests above
532     // ---------------------------------------------------------------
533
534     // ---------------------------------------------------------------
535     // Utilities: setup routines for search tests
536     // ---------------------------------------------------------------
537
538     public void createAuthority() throws Exception {
539
540         String testName = "createAuthority";
541         if (logger.isDebugEnabled()) {
542             logger.debug(getTestBanner(testName, CLASS_NAME));
543         }
544
545         // Perform setup.
546         int expectedStatusCode = Response.Status.CREATED.getStatusCode();
547         ServiceRequestType requestType = ServiceRequestType.CREATE;
548         testSetup(expectedStatusCode, requestType);
549
550         // Submit the request to the service and store the response.
551         PersonAuthorityClient client = new PersonAuthorityClient();
552         String shortId = createIdentifier();
553         String displayName = "displayName-" + shortId;
554         //String baseRefName = PersonAuthorityClientUtils.createPersonAuthRefName(shortId, null);
555         PoxPayloadOut multipart =
556             PersonAuthorityClientUtils.createPersonAuthorityInstance(
557             displayName, shortId, client.getCommonPartName());
558
559         String newID = null;
560         Response res = client.create(multipart);
561         try {
562             assertStatusCode(res, testName);
563             newID = PersonAuthorityClientUtils.extractId(res);
564         } finally {
565                 if (res != null) {
566                 res.close();
567             }
568         }
569         // Store the refname from the first resource created
570         // for additional tests below.
571         //knownResourceRefName = baseRefName;
572         // Store the ID returned from the first resource created
573         // for additional tests below.
574         if (knownResourceId == null){
575             knownResourceId = newID;
576             //knownResourceRefName = baseRefName;
577         }
578
579         // Store the IDs from every resource created by tests,
580         // so they can be deleted after tests have been run.
581         allResourceIdsCreated.add(newID);
582     }
583
584      /**
585      * Creates an item in the authority, used for partial term matching tests.
586      *
587      * @param authorityCsid The CSID of the Authority in which the term will be created.
588      * @param authRefName The refName of the Authority in which the term will be created.
589      */
590     private void createItemsInAuthorityForPartialTermMatch(
591                 String authorityCsid, String authRefName)
592         throws Exception {
593             
594         String testName = "createItemsInAuthorityForPartialTermMatch";
595
596         int expectedStatusCode = Response.Status.CREATED.getStatusCode();
597         ServiceRequestType requestType = ServiceRequestType.CREATE;
598         testSetup(expectedStatusCode, requestType);
599
600         // Submit the request to the service and store the response.
601         PersonAuthorityClient client = new PersonAuthorityClient();
602         Map<String, String> partialTermPersonMap = new HashMap<String,String>();
603         //
604         // Fill values for the UNICODE item
605         //
606         partialTermPersonMap.put(PersonJAXBSchema.SHORT_IDENTIFIER, TEST_SHORT_ID_UNICODE );
607         partialTermPersonMap.put(PersonJAXBSchema.BIRTH_PLACE, TEST_KWD_BIRTH_PLACE);
608         partialTermPersonMap.put(PersonJAXBSchema.GENDER, "male");
609         partialTermPersonMap.put(PersonJAXBSchema.BIO_NOTE, TEST_KWD_BIO_NOTE_NO_QUOTES);
610         
611         List<PersonTermGroup> partialTerms = new ArrayList<PersonTermGroup>();
612         PersonTermGroup term = new PersonTermGroup();
613         term.setTermDisplayName(TEST_PARTIAL_TERM_DISPLAY_NAME_UNICODE);
614         term.setTermName(TEST_PARTIAL_TERM_DISPLAY_NAME_UNICODE);
615         term.setForeName(TEST_PARTIAL_TERM_FORE_NAME);
616         term.setSurName(TEST_PARTIAL_TERM_SUR_NAME_UNICODE);
617         partialTerms.add(term);
618
619         Map<String, List<String>> partialTermRepeatablesMap = new HashMap<String, List<String>>();
620         ArrayList<String> styles = new ArrayList<String>();
621         styles.add(TEST_KWD_UTF8_STYLE);
622         partialTermRepeatablesMap.put(PersonJAXBSchema.SCHOOLS_OR_STYLES, styles);
623
624         createItem(testName, authorityCsid, null /*authRefName*/, client, 
625                 partialTermPersonMap, partialTerms, partialTermRepeatablesMap);
626         //
627         // Adjust values for the QUOTE item
628         //
629         partialTermPersonMap.put(PersonJAXBSchema.SHORT_IDENTIFIER, TEST_SHORT_ID_QUOTE );
630         partialTermPersonMap.put(PersonJAXBSchema.BIO_NOTE, TEST_KWD_BIO_NOTE_DBL_QUOTES);
631         
632         partialTerms.get(0).setTermDisplayName(TEST_PARTIAL_TERM_DISPLAY_NAME_QUOTE);
633         partialTerms.get(0).setSurName(TEST_PARTIAL_TERM_SUR_NAME_QUOTE);
634
635         createItem(testName, authorityCsid, null /*authRefName*/, client, 
636                 partialTermPersonMap, partialTerms, partialTermRepeatablesMap);
637     }
638     
639     private void createItem(
640                 String testName, 
641                 String authorityCsid, 
642                 String authRefName,
643                 PersonAuthorityClient client,
644                 Map<String, String> partialTermPersonMap,
645                 List<PersonTermGroup> partialTerms,
646                 Map<String, List<String>> partialTermRepeatablesMap) throws Exception {
647         PoxPayloadOut multipart =
648             PersonAuthorityClientUtils.createPersonInstance(authorityCsid, null, //authRefName, 
649                 partialTermPersonMap, partialTerms, partialTermRepeatablesMap, client.getItemCommonPartName() );
650
651         String newID = null;
652         Response res = client.createItem(authorityCsid, multipart);
653         try {
654             newID = PersonAuthorityClientUtils.extractId(res);
655         } finally {
656                 if (res != null) {
657                 res.close();
658             }
659         }
660
661         // Store the ID returned from the first item resource created
662         // for additional tests below.
663         if (knownItemResourceId == null){
664             knownItemResourceId = newID;
665             if (logger.isDebugEnabled()) {
666                 logger.debug(testName + ": knownItemPartialTermResourceId=" + knownItemPartialTermResourceId);
667             }
668         }
669
670         // Store the IDs from any item resources created
671         // by tests, along with the IDs of their parents, so these items
672         // can be deleted after all tests have been run.
673         allItemResourceIdsCreated.put(newID, authorityCsid);
674     }
675
676 }